opennms-api-wrapper 0.2.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.
- opennms_api_wrapper-0.2.0/CHANGELOG.md +54 -0
- opennms_api_wrapper-0.2.0/CLAUDE.md +149 -0
- opennms_api_wrapper-0.2.0/LICENSE +21 -0
- opennms_api_wrapper-0.2.0/MANIFEST.in +2 -0
- opennms_api_wrapper-0.2.0/PKG-INFO +232 -0
- opennms_api_wrapper-0.2.0/README.md +176 -0
- opennms_api_wrapper-0.2.0/opennms_api_wrapper/__init__.py +10 -0
- opennms_api_wrapper-0.2.0/opennms_api_wrapper/_acks.py +52 -0
- opennms_api_wrapper-0.2.0/opennms_api_wrapper/_alarm_history.py +30 -0
- opennms_api_wrapper-0.2.0/opennms_api_wrapper/_alarm_stats.py +24 -0
- opennms_api_wrapper-0.2.0/opennms_api_wrapper/_alarms.py +130 -0
- opennms_api_wrapper-0.2.0/opennms_api_wrapper/_base.py +104 -0
- opennms_api_wrapper-0.2.0/opennms_api_wrapper/_business_services.py +42 -0
- opennms_api_wrapper-0.2.0/opennms_api_wrapper/_categories.py +73 -0
- opennms_api_wrapper-0.2.0/opennms_api_wrapper/_device_config.py +102 -0
- opennms_api_wrapper-0.2.0/opennms_api_wrapper/_discovery.py +48 -0
- opennms_api_wrapper-0.2.0/opennms_api_wrapper/_events.py +83 -0
- opennms_api_wrapper-0.2.0/opennms_api_wrapper/_flows.py +235 -0
- opennms_api_wrapper-0.2.0/opennms_api_wrapper/_foreign_sources.py +123 -0
- opennms_api_wrapper-0.2.0/opennms_api_wrapper/_graphs.py +65 -0
- opennms_api_wrapper-0.2.0/opennms_api_wrapper/_groups.py +69 -0
- opennms_api_wrapper-0.2.0/opennms_api_wrapper/_heatmap.py +63 -0
- opennms_api_wrapper-0.2.0/opennms_api_wrapper/_info.py +12 -0
- opennms_api_wrapper-0.2.0/opennms_api_wrapper/_ipinterfaces_v2.py +22 -0
- opennms_api_wrapper-0.2.0/opennms_api_wrapper/_ksc_reports.py +49 -0
- opennms_api_wrapper-0.2.0/opennms_api_wrapper/_maps.py +36 -0
- opennms_api_wrapper-0.2.0/opennms_api_wrapper/_measurements.py +75 -0
- opennms_api_wrapper-0.2.0/opennms_api_wrapper/_metadata.py +207 -0
- opennms_api_wrapper-0.2.0/opennms_api_wrapper/_nodes.py +301 -0
- opennms_api_wrapper-0.2.0/opennms_api_wrapper/_notifications.py +35 -0
- opennms_api_wrapper-0.2.0/opennms_api_wrapper/_outages.py +35 -0
- opennms_api_wrapper-0.2.0/opennms_api_wrapper/_requisitions.py +249 -0
- opennms_api_wrapper-0.2.0/opennms_api_wrapper/_resources.py +66 -0
- opennms_api_wrapper-0.2.0/opennms_api_wrapper/_sched_outages.py +81 -0
- opennms_api_wrapper-0.2.0/opennms_api_wrapper/_situations.py +81 -0
- opennms_api_wrapper-0.2.0/opennms_api_wrapper/_snmp_config.py +31 -0
- opennms_api_wrapper-0.2.0/opennms_api_wrapper/_snmpinterfaces_v2.py +22 -0
- opennms_api_wrapper-0.2.0/opennms_api_wrapper/_users.py +53 -0
- opennms_api_wrapper-0.2.0/opennms_api_wrapper/client.py +122 -0
- opennms_api_wrapper-0.2.0/opennms_api_wrapper.egg-info/PKG-INFO +232 -0
- opennms_api_wrapper-0.2.0/opennms_api_wrapper.egg-info/SOURCES.txt +74 -0
- opennms_api_wrapper-0.2.0/opennms_api_wrapper.egg-info/dependency_links.txt +1 -0
- opennms_api_wrapper-0.2.0/opennms_api_wrapper.egg-info/requires.txt +5 -0
- opennms_api_wrapper-0.2.0/opennms_api_wrapper.egg-info/top_level.txt +1 -0
- opennms_api_wrapper-0.2.0/pyproject.toml +51 -0
- opennms_api_wrapper-0.2.0/setup.cfg +4 -0
- opennms_api_wrapper-0.2.0/tests/test_acks.py +86 -0
- opennms_api_wrapper-0.2.0/tests/test_alarm_history.py +44 -0
- opennms_api_wrapper-0.2.0/tests/test_alarm_stats.py +36 -0
- opennms_api_wrapper-0.2.0/tests/test_alarms.py +147 -0
- opennms_api_wrapper-0.2.0/tests/test_business_services.py +65 -0
- opennms_api_wrapper-0.2.0/tests/test_categories.py +103 -0
- opennms_api_wrapper-0.2.0/tests/test_device_config.py +127 -0
- opennms_api_wrapper-0.2.0/tests/test_discovery.py +63 -0
- opennms_api_wrapper-0.2.0/tests/test_events.py +92 -0
- opennms_api_wrapper-0.2.0/tests/test_flows.py +139 -0
- opennms_api_wrapper-0.2.0/tests/test_foreign_sources.py +149 -0
- opennms_api_wrapper-0.2.0/tests/test_graphs.py +72 -0
- opennms_api_wrapper-0.2.0/tests/test_groups.py +95 -0
- opennms_api_wrapper-0.2.0/tests/test_heatmap.py +94 -0
- opennms_api_wrapper-0.2.0/tests/test_info.py +18 -0
- opennms_api_wrapper-0.2.0/tests/test_ipinterfaces_v2.py +53 -0
- opennms_api_wrapper-0.2.0/tests/test_ksc_reports.py +48 -0
- opennms_api_wrapper-0.2.0/tests/test_maps.py +56 -0
- opennms_api_wrapper-0.2.0/tests/test_measurements.py +87 -0
- opennms_api_wrapper-0.2.0/tests/test_metadata.py +223 -0
- opennms_api_wrapper-0.2.0/tests/test_nodes.py +355 -0
- opennms_api_wrapper-0.2.0/tests/test_notifications.py +50 -0
- opennms_api_wrapper-0.2.0/tests/test_outages.py +49 -0
- opennms_api_wrapper-0.2.0/tests/test_requisitions.py +294 -0
- opennms_api_wrapper-0.2.0/tests/test_resources.py +58 -0
- opennms_api_wrapper-0.2.0/tests/test_sched_outages.py +113 -0
- opennms_api_wrapper-0.2.0/tests/test_situations.py +123 -0
- opennms_api_wrapper-0.2.0/tests/test_snmp_config.py +54 -0
- opennms_api_wrapper-0.2.0/tests/test_snmpinterfaces_v2.py +54 -0
- opennms_api_wrapper-0.2.0/tests/test_users.py +76 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.2.0] - 2026-03-07
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- Accept header now includes `text/plain;q=0.9` to prevent 406 errors on
|
|
13
|
+
`/count` endpoints in some OpenNMS versions.
|
|
14
|
+
- `get_node_count()` uses the v2 API (`GET /api/v2/nodes?limit=1`) and
|
|
15
|
+
extracts `totalCount`. The v1 `/rest/nodes` endpoint does not expose a
|
|
16
|
+
`/count` sub-resource.
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- Smoke test: endpoints that depend on optional plugins (alarm history,
|
|
21
|
+
hardware inventory, flows, situations) or heavy queries (resources) now
|
|
22
|
+
report as WARN instead of FAIL. Each warning cites the required plugin
|
|
23
|
+
or feature.
|
|
24
|
+
- Smoke test: events query filters by lowest-ID node to avoid full table
|
|
25
|
+
scans on large databases.
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
|
|
29
|
+
- Smoke test: `--skip` flag to skip tests by label prefix (e.g.,
|
|
30
|
+
`--skip get_flow` skips all flow tests).
|
|
31
|
+
- Smoke test: `OPENNMS_TIMEOUT` env var (default 60 seconds).
|
|
32
|
+
- Validated against OpenNMS Meridian 2024.3.0 (65 passed, 0 failed).
|
|
33
|
+
|
|
34
|
+
## [0.1.0] - 2026-03-06
|
|
35
|
+
|
|
36
|
+
### Added
|
|
37
|
+
|
|
38
|
+
- Initial release covering all OpenNMS Horizon 35 REST API endpoints (v1
|
|
39
|
+
and v2).
|
|
40
|
+
- Single `OpenNMS` client class importable as `import opennms_api_wrapper as
|
|
41
|
+
opennms`.
|
|
42
|
+
- JSON-only request/response handling throughout; no XML dependency.
|
|
43
|
+
- Synchronous, dependency-minimal design (only `requests` required at
|
|
44
|
+
runtime).
|
|
45
|
+
- 290-test suite with full method coverage; HTTP mocked at the adapter level
|
|
46
|
+
using the `responses` library — no live server required to run tests.
|
|
47
|
+
- Resource groups covered: alarms, alarm statistics, alarm history, events,
|
|
48
|
+
nodes (with IP interfaces, SNMP interfaces, monitored services, categories,
|
|
49
|
+
assets, and hardware inventory), outages, notifications, acknowledgements,
|
|
50
|
+
requisitions, foreign sources, SNMP configuration, groups, users,
|
|
51
|
+
categories, scheduled outages, KSC reports, resources, measurements,
|
|
52
|
+
heatmap, maps, topology graphs, flows, device configuration, situations
|
|
53
|
+
(v2), business services (v2), metadata (v2), server info, discovery (v2),
|
|
54
|
+
and global IP/SNMP interface views (v2).
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# CLAUDE.md — opennms-api-wrapper
|
|
2
|
+
|
|
3
|
+
This file gives Claude Code the context needed to work on this project
|
|
4
|
+
without prior conversation history.
|
|
5
|
+
|
|
6
|
+
## Project purpose
|
|
7
|
+
|
|
8
|
+
A thin, synchronous Python 3 wrapper for the OpenNMS REST API (Horizon 35).
|
|
9
|
+
Users `import opennms_api_wrapper as opennms` and get a single `OpenNMS`
|
|
10
|
+
client class with one method per API endpoint.
|
|
11
|
+
|
|
12
|
+
## Repository layout
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
opennms_api_wrapper/ # installable package
|
|
16
|
+
__init__.py # exports OpenNMS, __version__
|
|
17
|
+
client.py # OpenNMS class (combines all mixins)
|
|
18
|
+
_base.py # _OpenNMSBase: HTTP helpers (_get/_post/_put/_delete/_parse)
|
|
19
|
+
_alarms.py # AlarmsMixin
|
|
20
|
+
_alarm_stats.py # AlarmStatsMixin
|
|
21
|
+
_alarm_history.py # AlarmHistoryMixin
|
|
22
|
+
_events.py # EventsMixin
|
|
23
|
+
_nodes.py # NodesMixin (largest: nodes + sub-resources)
|
|
24
|
+
_outages.py # OutagesMixin
|
|
25
|
+
_notifications.py # NotificationsMixin
|
|
26
|
+
_acks.py # AcksMixin
|
|
27
|
+
_requisitions.py # RequisitionsMixin
|
|
28
|
+
_foreign_sources.py # ForeignSourcesMixin
|
|
29
|
+
_snmp_config.py # SnmpConfigMixin
|
|
30
|
+
_groups.py # GroupsMixin
|
|
31
|
+
_users.py # UsersMixin
|
|
32
|
+
_categories.py # CategoriesMixin
|
|
33
|
+
_sched_outages.py # SchedOutagesMixin
|
|
34
|
+
_ksc_reports.py # KscReportsMixin
|
|
35
|
+
_resources.py # ResourcesMixin
|
|
36
|
+
_measurements.py # MeasurementsMixin
|
|
37
|
+
_heatmap.py # HeatmapMixin
|
|
38
|
+
_maps.py # MapsMixin
|
|
39
|
+
_graphs.py # GraphsMixin
|
|
40
|
+
_flows.py # FlowsMixin
|
|
41
|
+
_device_config.py # DeviceConfigMixin
|
|
42
|
+
_situations.py # SituationsMixin (v2)
|
|
43
|
+
_business_services.py # BusinessServicesMixin (v2)
|
|
44
|
+
_metadata.py # MetadataMixin (v2, largest: node/iface/service metadata)
|
|
45
|
+
_info.py # InfoMixin
|
|
46
|
+
_discovery.py # DiscoveryMixin (v2)
|
|
47
|
+
_ipinterfaces_v2.py # IpInterfacesV2Mixin
|
|
48
|
+
_snmpinterfaces_v2.py # SnmpInterfacesV2Mixin
|
|
49
|
+
|
|
50
|
+
tests/
|
|
51
|
+
conftest.py # client fixture, V1/V2 URL constants, qs() helper
|
|
52
|
+
fixtures.py # all accurate OpenNMS Horizon 35 response shapes
|
|
53
|
+
test_*.py # one file per mixin (30 files, 290 tests total)
|
|
54
|
+
|
|
55
|
+
dist/ # built artifacts (gitignored)
|
|
56
|
+
pyproject.toml # build config + project metadata
|
|
57
|
+
smoke_test.py # live-server smoke test (read-only + --write mode)
|
|
58
|
+
# python smoke_test.py # read-only, safe for any server
|
|
59
|
+
# python smoke_test.py --write # write ops, prompts for confirmation
|
|
60
|
+
# python smoke_test.py --write --yes # skip prompt (CI only)
|
|
61
|
+
# python smoke_test.py --no-color # plain output for log files
|
|
62
|
+
# python smoke_test.py --skip get_flow # skip by label prefix
|
|
63
|
+
# env vars: OPENNMS_URL, OPENNMS_USER, OPENNMS_PASSWORD,
|
|
64
|
+
# OPENNMS_VERIFY_SSL, OPENNMS_TIMEOUT
|
|
65
|
+
ARCHITECTURE.md # architecture decision records (ADRs)
|
|
66
|
+
MERMAID.md # Mermaid architecture diagrams
|
|
67
|
+
CHANGELOG.md
|
|
68
|
+
README.md
|
|
69
|
+
CONTRIBUTING.md
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Architecture decisions (do not change without good reason)
|
|
73
|
+
|
|
74
|
+
- **Mixin pattern**: each resource group lives in its own `_<name>.py` mixin.
|
|
75
|
+
`client.py` combines them all via multiple inheritance into `OpenNMS`.
|
|
76
|
+
- **JSON only**: all request bodies are JSON. No XML anywhere.
|
|
77
|
+
The one exception: `POST /rest/acks` uses `application/x-www-form-urlencoded`
|
|
78
|
+
because the OpenNMS API requires it — handled via `form_data=` in `_post`.
|
|
79
|
+
- **Synchronous only**: no async. `requests.Session` is used throughout.
|
|
80
|
+
One runtime dependency: `requests>=2.28`.
|
|
81
|
+
- **v1 vs v2**: v1 endpoints live at `/opennms/rest/`, v2 at
|
|
82
|
+
`/opennms/api/v2/`. Every `_get/_post/_put/_delete` accepts `v2=True`.
|
|
83
|
+
- **Accept header**: `application/json, text/plain;q=0.9`. Some OpenNMS
|
|
84
|
+
versions return 406 if the Accept header does not include `text/plain` for
|
|
85
|
+
`/count` endpoints. JSON stays preferred via implicit q=1.0.
|
|
86
|
+
- **`_parse()`** handles three response types:
|
|
87
|
+
- `application/json` → `resp.json()`
|
|
88
|
+
- `text/plain` → `int(text)` if possible, else `str`
|
|
89
|
+
- empty body (204 No Content) → `None`
|
|
90
|
+
- **Node count via v2**: `get_node_count()` uses `GET /api/v2/nodes?limit=1`
|
|
91
|
+
and extracts `totalCount`. The v1 `/rest/nodes` endpoint does not have a
|
|
92
|
+
`/count` sub-resource — it routes all sub-paths as node criteria.
|
|
93
|
+
- **Timeout**: `_OpenNMSBase.__init__` accepts `timeout=30` (seconds). Passed
|
|
94
|
+
to every `_session.get/post/put/delete` call. `OpenNMS.__init__` exposes it
|
|
95
|
+
as a public parameter.
|
|
96
|
+
- **Smoke test warn level**: endpoints that depend on optional plugins or
|
|
97
|
+
heavy server-side queries use `warn()` instead of `run()`. Warnings are
|
|
98
|
+
non-fatal and include the required plugin/feature name. Only hard `FAIL`s
|
|
99
|
+
cause a non-zero exit code.
|
|
100
|
+
|
|
101
|
+
## Development environment
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
python3 -m venv .venv
|
|
105
|
+
source .venv/bin/activate
|
|
106
|
+
pip install -e ".[dev]" # installs requests + pytest + responses
|
|
107
|
+
pytest tests/ -v # run full suite (290 tests, ~0.2 s)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Always activate the `.venv` before running any commands — never rely on the
|
|
111
|
+
system Python or system pip.
|
|
112
|
+
|
|
113
|
+
## Test conventions
|
|
114
|
+
|
|
115
|
+
- HTTP mocking: `responses` library with `@responses.activate` decorator.
|
|
116
|
+
- `conftest.py` constants:
|
|
117
|
+
- `V1 = "http://opennms:8980/opennms/rest"`
|
|
118
|
+
- `V2 = "http://opennms:8980/opennms/api/v2"`
|
|
119
|
+
- `qs(url)` parses query params from a URL into a dict of lists.
|
|
120
|
+
- Fixture shapes in `tests/fixtures.py` mirror real OpenNMS Horizon 35
|
|
121
|
+
responses (singular resource name as list wrapper key, plus `totalCount`,
|
|
122
|
+
`count`, `offset`).
|
|
123
|
+
- **URL encoding gotcha**: `requests` percent-encodes spaces in URL path
|
|
124
|
+
segments as `%20`, not `+`. Mock URLs for paths with spaces must use `%20`
|
|
125
|
+
explicitly, e.g. `Do%20Not%20Persist%20Discovered%20IPs`.
|
|
126
|
+
- 204 responses return `None`; plain-text count endpoints return `int`.
|
|
127
|
+
- Verify request bodies with `json.loads(responses.calls[0].request.body)`.
|
|
128
|
+
|
|
129
|
+
## Build / release
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
pip install build
|
|
133
|
+
python -m build # produces dist/*.tar.gz and dist/*.whl
|
|
134
|
+
pip install twine
|
|
135
|
+
twine upload dist/* # publish to PyPI
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
The build backend is `setuptools.build_meta` (in `pyproject.toml`).
|
|
139
|
+
The older path `setuptools.backends.legacy:build` does not work — do not use it.
|
|
140
|
+
|
|
141
|
+
## Style
|
|
142
|
+
|
|
143
|
+
- PEP 8 throughout: 79-character line limit, 4-space indentation.
|
|
144
|
+
- Every public method has a Google-style docstring with `Args:` and `Returns:`
|
|
145
|
+
sections where non-trivial — required for autodoc compatibility (Sphinx,
|
|
146
|
+
pdoc, mkdocstrings). Private helpers have at minimum a one-line docstring.
|
|
147
|
+
- No inline comments on code that is self-evident.
|
|
148
|
+
- No error handling for scenarios that cannot happen.
|
|
149
|
+
- No abstractions introduced for one-off operations.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Richard "Chance" Newkirk
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: opennms-api-wrapper
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: A thin Python wrapper for the OpenNMS REST API (Horizon 35)
|
|
5
|
+
Author-email: "Richard \"Chance\" Newkirk" <chance.newkirk+github@pm.me>
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2026 Richard "Chance" Newkirk
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: Homepage, https://github.com/cnewkirk/opennms-api-wrapper
|
|
29
|
+
Project-URL: Repository, https://github.com/cnewkirk/opennms-api-wrapper
|
|
30
|
+
Project-URL: Bug Tracker, https://github.com/cnewkirk/opennms-api-wrapper/issues
|
|
31
|
+
Project-URL: Changelog, https://github.com/cnewkirk/opennms-api-wrapper/blob/main/CHANGELOG.md
|
|
32
|
+
Keywords: opennms,network-management,rest,api,wrapper,nms
|
|
33
|
+
Classifier: Development Status :: 4 - Beta
|
|
34
|
+
Classifier: Intended Audience :: Developers
|
|
35
|
+
Classifier: Intended Audience :: System Administrators
|
|
36
|
+
Classifier: Intended Audience :: Telecommunications Industry
|
|
37
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
38
|
+
Classifier: Topic :: System :: Networking :: Monitoring
|
|
39
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
40
|
+
Classifier: Programming Language :: Python :: 3
|
|
41
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
42
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
43
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
44
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
45
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
46
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
47
|
+
Classifier: Operating System :: OS Independent
|
|
48
|
+
Requires-Python: >=3.8
|
|
49
|
+
Description-Content-Type: text/markdown
|
|
50
|
+
License-File: LICENSE
|
|
51
|
+
Requires-Dist: requests>=2.28
|
|
52
|
+
Provides-Extra: dev
|
|
53
|
+
Requires-Dist: pytest; extra == "dev"
|
|
54
|
+
Requires-Dist: responses; extra == "dev"
|
|
55
|
+
Dynamic: license-file
|
|
56
|
+
|
|
57
|
+
# opennms-api-wrapper
|
|
58
|
+
|
|
59
|
+
[](https://github.com/cnewkirk/opennms-api-wrapper/actions/workflows/ci.yml)
|
|
60
|
+
[](https://github.com/cnewkirk/opennms-api-wrapper/releases)
|
|
61
|
+
[](https://www.python.org/)
|
|
62
|
+
[](LICENSE)
|
|
63
|
+
|
|
64
|
+
A thin, dependency-minimal Python 3 wrapper for the
|
|
65
|
+
[OpenNMS](https://www.opennms.com/) REST API (Horizon 35+).
|
|
66
|
+
Validated against OpenNMS Meridian 2024.3.0 with a live-server smoke test
|
|
67
|
+
suite.
|
|
68
|
+
|
|
69
|
+
## Features
|
|
70
|
+
|
|
71
|
+
- Covers every v1 (`/opennms/rest/`) and v2 (`/opennms/api/v2/`) endpoint
|
|
72
|
+
- JSON everywhere — no XML handling required
|
|
73
|
+
- Single runtime dependency: [`requests`](https://docs.python-requests.org/)
|
|
74
|
+
- Synchronous and straightforward — no async complexity
|
|
75
|
+
- 290-test suite with full method coverage (mocked HTTP — no live server required)
|
|
76
|
+
- Live-server smoke test validated against Meridian 2024.3.0
|
|
77
|
+
|
|
78
|
+
## Installation
|
|
79
|
+
|
|
80
|
+
**From the GitHub release** (no clone required — recommended for most users):
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
pip install https://github.com/cnewkirk/opennms-api-wrapper/archive/refs/tags/v0.2.0.tar.gz
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**From source** (clone first, then install):
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
git clone https://github.com/cnewkirk/opennms-api-wrapper.git
|
|
90
|
+
cd opennms-api-wrapper
|
|
91
|
+
pip install .
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
When the package is published to PyPI, installation will simplify to
|
|
95
|
+
`pip install opennms-api-wrapper`.
|
|
96
|
+
|
|
97
|
+
## Quick start
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
import opennms_api_wrapper as opennms
|
|
101
|
+
|
|
102
|
+
client = opennms.OpenNMS(
|
|
103
|
+
url="https://opennms.example.com:8443",
|
|
104
|
+
username="admin",
|
|
105
|
+
password="admin",
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
# Server info
|
|
109
|
+
info = client.get_info()
|
|
110
|
+
print(info["displayVersion"])
|
|
111
|
+
|
|
112
|
+
# List alarms
|
|
113
|
+
alarms = client.get_alarms(limit=25, order_by="lastEventTime", order="desc")
|
|
114
|
+
for alarm in alarms["alarm"]:
|
|
115
|
+
print(alarm["id"], alarm["severity"], alarm["nodeLabel"])
|
|
116
|
+
|
|
117
|
+
# Acknowledge an alarm
|
|
118
|
+
client.ack_alarm(alarm_id=42)
|
|
119
|
+
|
|
120
|
+
# List alarms with FIQL filter (v2)
|
|
121
|
+
alarms = client.get_alarms_v2(fiql="severity==MAJOR")
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## API coverage
|
|
125
|
+
|
|
126
|
+
| Resource group | Methods |
|
|
127
|
+
|---|---|
|
|
128
|
+
| Alarms (v1 + v2) | list, get, count, ack/unack/clear/escalate, bulk ops |
|
|
129
|
+
| Alarm statistics | stats, stats by severity |
|
|
130
|
+
| Alarm history | history, history at timestamp, state changes |
|
|
131
|
+
| Events | list, get, count, create, ack/unack, bulk ack/unack |
|
|
132
|
+
| Nodes | full CRUD + IP interfaces, SNMP interfaces, services, categories, assets, hardware |
|
|
133
|
+
| Outages | list, get, count, node outages |
|
|
134
|
+
| Notifications | list, get, count, trigger destination path |
|
|
135
|
+
| Acknowledgements | list, get, count, create, ack/unack notification |
|
|
136
|
+
| Requisitions | full CRUD including nodes, interfaces, services, categories, assets |
|
|
137
|
+
| Foreign sources | full CRUD including detectors and policies |
|
|
138
|
+
| SNMP configuration | get, set |
|
|
139
|
+
| Groups | full CRUD + user and category membership |
|
|
140
|
+
| Users | full CRUD + role assignment |
|
|
141
|
+
| Categories | full CRUD + node and group associations |
|
|
142
|
+
| Scheduled outages | full CRUD + daemon associations |
|
|
143
|
+
| KSC reports | list, get, count, create, update |
|
|
144
|
+
| Resources | list, get, get for node, select, delete |
|
|
145
|
+
| Measurements | single attribute (GET), multi-source (POST) |
|
|
146
|
+
| Heatmap | outages + alarms × categories / foreign sources / services / nodes |
|
|
147
|
+
| Maps | full CRUD + map elements |
|
|
148
|
+
| Topology graphs | containers, graph, graph view (POST), search suggestions, search results |
|
|
149
|
+
| Flows | count, exporters, applications, conversations, hosts |
|
|
150
|
+
| Device configuration | list, get, get by interface, latest, download, backup |
|
|
151
|
+
| Situations (v2) | list, create, add alarms, clear, accept, remove alarms |
|
|
152
|
+
| Business services (v2) | full CRUD |
|
|
153
|
+
| Metadata (v2) | full CRUD for node, interface, and service metadata |
|
|
154
|
+
| Server info | get |
|
|
155
|
+
| Discovery (v2) | submit scan configuration |
|
|
156
|
+
| IP interfaces (v2) | list with FIQL |
|
|
157
|
+
| SNMP interfaces (v2) | list with FIQL |
|
|
158
|
+
|
|
159
|
+
## Authentication
|
|
160
|
+
|
|
161
|
+
Basic authentication is used. Pass `verify_ssl=False` to disable certificate
|
|
162
|
+
verification (useful for self-signed certs in lab environments):
|
|
163
|
+
|
|
164
|
+
```python
|
|
165
|
+
client = opennms.OpenNMS(
|
|
166
|
+
url="https://opennms.example.com:8443",
|
|
167
|
+
username="admin",
|
|
168
|
+
password="admin",
|
|
169
|
+
verify_ssl=False,
|
|
170
|
+
)
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## Smoke testing
|
|
174
|
+
|
|
175
|
+
`smoke_test.py` exercises the wrapper against a real OpenNMS server. It is
|
|
176
|
+
intended for use against a dev or staging instance before each release — not
|
|
177
|
+
as a substitute for the 290-test mocked unit suite.
|
|
178
|
+
|
|
179
|
+
Tests that depend on optional plugins or heavy endpoints are reported as
|
|
180
|
+
**WARN** (non-fatal) rather than FAIL. Each warning includes the specific
|
|
181
|
+
plugin or feature required.
|
|
182
|
+
|
|
183
|
+
**Read-only mode** (default) is safe to run against any server, including
|
|
184
|
+
production. It issues only GET requests and makes no changes.
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
export OPENNMS_URL="https://opennms.example.com:8443"
|
|
188
|
+
export OPENNMS_USER="admin"
|
|
189
|
+
export OPENNMS_PASSWORD="secret"
|
|
190
|
+
export OPENNMS_VERIFY_SSL="false" # omit or set to "true" for valid certs
|
|
191
|
+
export OPENNMS_TIMEOUT="60" # per-request timeout in seconds (default 60)
|
|
192
|
+
|
|
193
|
+
python smoke_test.py
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
**Write mode** creates and then deletes objects on the server (events,
|
|
197
|
+
categories, groups, requisitions, maps, etc.). It will prompt for explicit
|
|
198
|
+
confirmation and print the target URL before running a single write.
|
|
199
|
+
**Only use write mode against a dev or staging instance — never production.**
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
python smoke_test.py --write # interactive prompt required
|
|
203
|
+
python smoke_test.py --write --yes # skip prompt (CI pipelines only)
|
|
204
|
+
python smoke_test.py --no-color # plain output for log files
|
|
205
|
+
python smoke_test.py --skip get_resources --skip get_flow # skip slow tests
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
The `--skip` flag accepts a prefix — `--skip get_flow` skips all tests
|
|
209
|
+
whose label starts with `get_flow`.
|
|
210
|
+
|
|
211
|
+
## Development
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
git clone https://github.com/cnewkirk/opennms-api-wrapper.git
|
|
215
|
+
cd opennms-api-wrapper
|
|
216
|
+
python3 -m venv .venv
|
|
217
|
+
source .venv/bin/activate
|
|
218
|
+
pip install -e ".[dev]"
|
|
219
|
+
pytest tests/ -v
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## Contributing
|
|
223
|
+
|
|
224
|
+
Bug reports and pull requests are welcome on GitHub at
|
|
225
|
+
https://github.com/cnewkirk/opennms-api-wrapper.
|
|
226
|
+
|
|
227
|
+
## Acknowledgements
|
|
228
|
+
|
|
229
|
+
This library was designed and tested by a human, with implementation
|
|
230
|
+
assistance from [Claude Code](https://claude.ai/code) (Anthropic). All API
|
|
231
|
+
shapes are derived from the official OpenNMS Horizon 35 REST API
|
|
232
|
+
documentation.
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# opennms-api-wrapper
|
|
2
|
+
|
|
3
|
+
[](https://github.com/cnewkirk/opennms-api-wrapper/actions/workflows/ci.yml)
|
|
4
|
+
[](https://github.com/cnewkirk/opennms-api-wrapper/releases)
|
|
5
|
+
[](https://www.python.org/)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
|
|
8
|
+
A thin, dependency-minimal Python 3 wrapper for the
|
|
9
|
+
[OpenNMS](https://www.opennms.com/) REST API (Horizon 35+).
|
|
10
|
+
Validated against OpenNMS Meridian 2024.3.0 with a live-server smoke test
|
|
11
|
+
suite.
|
|
12
|
+
|
|
13
|
+
## Features
|
|
14
|
+
|
|
15
|
+
- Covers every v1 (`/opennms/rest/`) and v2 (`/opennms/api/v2/`) endpoint
|
|
16
|
+
- JSON everywhere — no XML handling required
|
|
17
|
+
- Single runtime dependency: [`requests`](https://docs.python-requests.org/)
|
|
18
|
+
- Synchronous and straightforward — no async complexity
|
|
19
|
+
- 290-test suite with full method coverage (mocked HTTP — no live server required)
|
|
20
|
+
- Live-server smoke test validated against Meridian 2024.3.0
|
|
21
|
+
|
|
22
|
+
## Installation
|
|
23
|
+
|
|
24
|
+
**From the GitHub release** (no clone required — recommended for most users):
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pip install https://github.com/cnewkirk/opennms-api-wrapper/archive/refs/tags/v0.2.0.tar.gz
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**From source** (clone first, then install):
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
git clone https://github.com/cnewkirk/opennms-api-wrapper.git
|
|
34
|
+
cd opennms-api-wrapper
|
|
35
|
+
pip install .
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
When the package is published to PyPI, installation will simplify to
|
|
39
|
+
`pip install opennms-api-wrapper`.
|
|
40
|
+
|
|
41
|
+
## Quick start
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
import opennms_api_wrapper as opennms
|
|
45
|
+
|
|
46
|
+
client = opennms.OpenNMS(
|
|
47
|
+
url="https://opennms.example.com:8443",
|
|
48
|
+
username="admin",
|
|
49
|
+
password="admin",
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
# Server info
|
|
53
|
+
info = client.get_info()
|
|
54
|
+
print(info["displayVersion"])
|
|
55
|
+
|
|
56
|
+
# List alarms
|
|
57
|
+
alarms = client.get_alarms(limit=25, order_by="lastEventTime", order="desc")
|
|
58
|
+
for alarm in alarms["alarm"]:
|
|
59
|
+
print(alarm["id"], alarm["severity"], alarm["nodeLabel"])
|
|
60
|
+
|
|
61
|
+
# Acknowledge an alarm
|
|
62
|
+
client.ack_alarm(alarm_id=42)
|
|
63
|
+
|
|
64
|
+
# List alarms with FIQL filter (v2)
|
|
65
|
+
alarms = client.get_alarms_v2(fiql="severity==MAJOR")
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## API coverage
|
|
69
|
+
|
|
70
|
+
| Resource group | Methods |
|
|
71
|
+
|---|---|
|
|
72
|
+
| Alarms (v1 + v2) | list, get, count, ack/unack/clear/escalate, bulk ops |
|
|
73
|
+
| Alarm statistics | stats, stats by severity |
|
|
74
|
+
| Alarm history | history, history at timestamp, state changes |
|
|
75
|
+
| Events | list, get, count, create, ack/unack, bulk ack/unack |
|
|
76
|
+
| Nodes | full CRUD + IP interfaces, SNMP interfaces, services, categories, assets, hardware |
|
|
77
|
+
| Outages | list, get, count, node outages |
|
|
78
|
+
| Notifications | list, get, count, trigger destination path |
|
|
79
|
+
| Acknowledgements | list, get, count, create, ack/unack notification |
|
|
80
|
+
| Requisitions | full CRUD including nodes, interfaces, services, categories, assets |
|
|
81
|
+
| Foreign sources | full CRUD including detectors and policies |
|
|
82
|
+
| SNMP configuration | get, set |
|
|
83
|
+
| Groups | full CRUD + user and category membership |
|
|
84
|
+
| Users | full CRUD + role assignment |
|
|
85
|
+
| Categories | full CRUD + node and group associations |
|
|
86
|
+
| Scheduled outages | full CRUD + daemon associations |
|
|
87
|
+
| KSC reports | list, get, count, create, update |
|
|
88
|
+
| Resources | list, get, get for node, select, delete |
|
|
89
|
+
| Measurements | single attribute (GET), multi-source (POST) |
|
|
90
|
+
| Heatmap | outages + alarms × categories / foreign sources / services / nodes |
|
|
91
|
+
| Maps | full CRUD + map elements |
|
|
92
|
+
| Topology graphs | containers, graph, graph view (POST), search suggestions, search results |
|
|
93
|
+
| Flows | count, exporters, applications, conversations, hosts |
|
|
94
|
+
| Device configuration | list, get, get by interface, latest, download, backup |
|
|
95
|
+
| Situations (v2) | list, create, add alarms, clear, accept, remove alarms |
|
|
96
|
+
| Business services (v2) | full CRUD |
|
|
97
|
+
| Metadata (v2) | full CRUD for node, interface, and service metadata |
|
|
98
|
+
| Server info | get |
|
|
99
|
+
| Discovery (v2) | submit scan configuration |
|
|
100
|
+
| IP interfaces (v2) | list with FIQL |
|
|
101
|
+
| SNMP interfaces (v2) | list with FIQL |
|
|
102
|
+
|
|
103
|
+
## Authentication
|
|
104
|
+
|
|
105
|
+
Basic authentication is used. Pass `verify_ssl=False` to disable certificate
|
|
106
|
+
verification (useful for self-signed certs in lab environments):
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
client = opennms.OpenNMS(
|
|
110
|
+
url="https://opennms.example.com:8443",
|
|
111
|
+
username="admin",
|
|
112
|
+
password="admin",
|
|
113
|
+
verify_ssl=False,
|
|
114
|
+
)
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Smoke testing
|
|
118
|
+
|
|
119
|
+
`smoke_test.py` exercises the wrapper against a real OpenNMS server. It is
|
|
120
|
+
intended for use against a dev or staging instance before each release — not
|
|
121
|
+
as a substitute for the 290-test mocked unit suite.
|
|
122
|
+
|
|
123
|
+
Tests that depend on optional plugins or heavy endpoints are reported as
|
|
124
|
+
**WARN** (non-fatal) rather than FAIL. Each warning includes the specific
|
|
125
|
+
plugin or feature required.
|
|
126
|
+
|
|
127
|
+
**Read-only mode** (default) is safe to run against any server, including
|
|
128
|
+
production. It issues only GET requests and makes no changes.
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
export OPENNMS_URL="https://opennms.example.com:8443"
|
|
132
|
+
export OPENNMS_USER="admin"
|
|
133
|
+
export OPENNMS_PASSWORD="secret"
|
|
134
|
+
export OPENNMS_VERIFY_SSL="false" # omit or set to "true" for valid certs
|
|
135
|
+
export OPENNMS_TIMEOUT="60" # per-request timeout in seconds (default 60)
|
|
136
|
+
|
|
137
|
+
python smoke_test.py
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
**Write mode** creates and then deletes objects on the server (events,
|
|
141
|
+
categories, groups, requisitions, maps, etc.). It will prompt for explicit
|
|
142
|
+
confirmation and print the target URL before running a single write.
|
|
143
|
+
**Only use write mode against a dev or staging instance — never production.**
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
python smoke_test.py --write # interactive prompt required
|
|
147
|
+
python smoke_test.py --write --yes # skip prompt (CI pipelines only)
|
|
148
|
+
python smoke_test.py --no-color # plain output for log files
|
|
149
|
+
python smoke_test.py --skip get_resources --skip get_flow # skip slow tests
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
The `--skip` flag accepts a prefix — `--skip get_flow` skips all tests
|
|
153
|
+
whose label starts with `get_flow`.
|
|
154
|
+
|
|
155
|
+
## Development
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
git clone https://github.com/cnewkirk/opennms-api-wrapper.git
|
|
159
|
+
cd opennms-api-wrapper
|
|
160
|
+
python3 -m venv .venv
|
|
161
|
+
source .venv/bin/activate
|
|
162
|
+
pip install -e ".[dev]"
|
|
163
|
+
pytest tests/ -v
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Contributing
|
|
167
|
+
|
|
168
|
+
Bug reports and pull requests are welcome on GitHub at
|
|
169
|
+
https://github.com/cnewkirk/opennms-api-wrapper.
|
|
170
|
+
|
|
171
|
+
## Acknowledgements
|
|
172
|
+
|
|
173
|
+
This library was designed and tested by a human, with implementation
|
|
174
|
+
assistance from [Claude Code](https://claude.ai/code) (Anthropic). All API
|
|
175
|
+
shapes are derived from the official OpenNMS Horizon 35 REST API
|
|
176
|
+
documentation.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"""opennms_api_wrapper – a thin Python wrapper for the OpenNMS REST API."""
|
|
2
|
+
from .client import OpenNMS
|
|
3
|
+
from importlib.metadata import version, PackageNotFoundError
|
|
4
|
+
|
|
5
|
+
__all__ = ["OpenNMS"]
|
|
6
|
+
|
|
7
|
+
try:
|
|
8
|
+
__version__ = version("opennms-api-wrapper")
|
|
9
|
+
except PackageNotFoundError:
|
|
10
|
+
__version__ = "unknown"
|