ceph-aiops 0.1.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.
Files changed (66) hide show
  1. ceph_aiops-0.1.0/.gitignore +7 -0
  2. ceph_aiops-0.1.0/CHANGELOG.md +61 -0
  3. ceph_aiops-0.1.0/LICENSE +21 -0
  4. ceph_aiops-0.1.0/PKG-INFO +137 -0
  5. ceph_aiops-0.1.0/README.md +121 -0
  6. ceph_aiops-0.1.0/RELEASE_NOTES.md +57 -0
  7. ceph_aiops-0.1.0/SECURITY.md +79 -0
  8. ceph_aiops-0.1.0/ceph_aiops/__init__.py +9 -0
  9. ceph_aiops-0.1.0/ceph_aiops/cli/__init__.py +9 -0
  10. ceph_aiops-0.1.0/ceph_aiops/cli/_common.py +78 -0
  11. ceph_aiops-0.1.0/ceph_aiops/cli/_root.py +57 -0
  12. ceph_aiops-0.1.0/ceph_aiops/cli/doctor.py +21 -0
  13. ceph_aiops-0.1.0/ceph_aiops/cli/health.py +35 -0
  14. ceph_aiops-0.1.0/ceph_aiops/cli/init.py +103 -0
  15. ceph_aiops-0.1.0/ceph_aiops/cli/osd.py +95 -0
  16. ceph_aiops-0.1.0/ceph_aiops/cli/overview.py +16 -0
  17. ceph_aiops-0.1.0/ceph_aiops/cli/secret.py +103 -0
  18. ceph_aiops-0.1.0/ceph_aiops/config.py +139 -0
  19. ceph_aiops-0.1.0/ceph_aiops/connection.py +205 -0
  20. ceph_aiops-0.1.0/ceph_aiops/doctor.py +86 -0
  21. ceph_aiops-0.1.0/ceph_aiops/governance/__init__.py +40 -0
  22. ceph_aiops-0.1.0/ceph_aiops/governance/audit.py +377 -0
  23. ceph_aiops-0.1.0/ceph_aiops/governance/budget.py +225 -0
  24. ceph_aiops-0.1.0/ceph_aiops/governance/decorators.py +474 -0
  25. ceph_aiops-0.1.0/ceph_aiops/governance/paths.py +23 -0
  26. ceph_aiops-0.1.0/ceph_aiops/governance/patterns.py +378 -0
  27. ceph_aiops-0.1.0/ceph_aiops/governance/policy.py +411 -0
  28. ceph_aiops-0.1.0/ceph_aiops/governance/sanitize.py +39 -0
  29. ceph_aiops-0.1.0/ceph_aiops/governance/undo.py +218 -0
  30. ceph_aiops-0.1.0/ceph_aiops/ops/__init__.py +1 -0
  31. ceph_aiops-0.1.0/ceph_aiops/ops/_util.py +44 -0
  32. ceph_aiops-0.1.0/ceph_aiops/ops/clusterops.py +192 -0
  33. ceph_aiops-0.1.0/ceph_aiops/ops/filesystem.py +107 -0
  34. ceph_aiops-0.1.0/ceph_aiops/ops/health.py +177 -0
  35. ceph_aiops-0.1.0/ceph_aiops/ops/osd.py +119 -0
  36. ceph_aiops-0.1.0/ceph_aiops/ops/overview.py +38 -0
  37. ceph_aiops-0.1.0/ceph_aiops/ops/pg.py +155 -0
  38. ceph_aiops-0.1.0/ceph_aiops/ops/pool.py +179 -0
  39. ceph_aiops-0.1.0/ceph_aiops/ops/rbd.py +77 -0
  40. ceph_aiops-0.1.0/ceph_aiops/secretstore.py +302 -0
  41. ceph_aiops-0.1.0/mcp_server/__init__.py +1 -0
  42. ceph_aiops-0.1.0/mcp_server/_shared.py +102 -0
  43. ceph_aiops-0.1.0/mcp_server/server.py +36 -0
  44. ceph_aiops-0.1.0/mcp_server/tools/__init__.py +1 -0
  45. ceph_aiops-0.1.0/mcp_server/tools/clusterops.py +121 -0
  46. ceph_aiops-0.1.0/mcp_server/tools/filesystem.py +37 -0
  47. ceph_aiops-0.1.0/mcp_server/tools/health.py +35 -0
  48. ceph_aiops-0.1.0/mcp_server/tools/osd.py +168 -0
  49. ceph_aiops-0.1.0/mcp_server/tools/pg.py +84 -0
  50. ceph_aiops-0.1.0/mcp_server/tools/pool.py +195 -0
  51. ceph_aiops-0.1.0/mcp_server/tools/rbd.py +106 -0
  52. ceph_aiops-0.1.0/pyproject.toml +59 -0
  53. ceph_aiops-0.1.0/server.json +21 -0
  54. ceph_aiops-0.1.0/skills/ceph-aiops/SKILL.md +114 -0
  55. ceph_aiops-0.1.0/skills/ceph-aiops/references/capabilities.md +61 -0
  56. ceph_aiops-0.1.0/skills/ceph-aiops/references/cli-reference.md +59 -0
  57. ceph_aiops-0.1.0/skills/ceph-aiops/references/setup-guide.md +125 -0
  58. ceph_aiops-0.1.0/smithery.yaml +9 -0
  59. ceph_aiops-0.1.0/tests/test_clusterops.py +101 -0
  60. ceph_aiops-0.1.0/tests/test_filesystem.py +91 -0
  61. ceph_aiops-0.1.0/tests/test_pg.py +65 -0
  62. ceph_aiops-0.1.0/tests/test_pool.py +107 -0
  63. ceph_aiops-0.1.0/tests/test_rbd.py +78 -0
  64. ceph_aiops-0.1.0/tests/test_secretstore.py +99 -0
  65. ceph_aiops-0.1.0/tests/test_smoke.py +264 -0
  66. ceph_aiops-0.1.0/uv.lock +962 -0
@@ -0,0 +1,7 @@
1
+ .venv/
2
+ dist/
3
+ __pycache__/
4
+ *.pyc
5
+ .pytest_cache/
6
+ .ruff_cache/
7
+ *.egg-info/
@@ -0,0 +1,61 @@
1
+ # Changelog
2
+
3
+ All notable changes to ceph-aiops are documented here. This project adheres
4
+ to [Semantic Versioning](https://semver.org/).
5
+
6
+ ## [0.1.0] — preview
7
+
8
+ Initial preview release: governed AI-ops for **Ceph** via the ceph-mgr Dashboard
9
+ REST API, with a bundled governance harness. Works against vanilla ceph-mgr
10
+ (cephadm / Proxmox-hosted / MicroCeph) — no croit, no Kubernetes.
11
+ **Mock-validated only — not yet verified against a live cluster.**
12
+
13
+ ### Added
14
+
15
+ - **35 MCP tools** (17 read, 18 write), every one wrapped with the bundled
16
+ `@governed_tool` harness (audit, policy, token/runaway budget, undo,
17
+ risk-tiers):
18
+ - **Health** — `cluster_health` (flagship RCA: per active HEALTH_WARN/ERR
19
+ check → plain-language cause + suggested action), `cluster_status`
20
+ (`ceph -s` summary).
21
+ - **OSD** — `osd_tree`, `osd_df` (most-full first + near/backfill-full flags),
22
+ `osd_perf` (slowest first); `cluster_flag_set` (low, undo — noout/noscrub/
23
+ nobackfill/norecover), `osd_reweight` (med, undo → prior weight; 0.0=drain),
24
+ `osd_mark_in` (med, undo), `osd_mark_out` (high, dry-run — drains data),
25
+ `osd_purge` (high, dry-run — irreversible).
26
+ - **PG** — `pg_summary` (state histogram + non-active+clean), `pg_dump_stuck`
27
+ (stuck PGs + implicated OSDs), `scrub_status` (overdue scrub/deep-scrub);
28
+ `trigger_scrub` (low), `trigger_deep_scrub` (low).
29
+ - **Pool** — `pool_ls`, `pool_df` (usable capacity = raw ÷ size);
30
+ `set_pool_quota` (med, undo), `set_pool_pg_num` (med, undo),
31
+ `set_pool_autoscale` (med, undo), `pool_create` (med), `set_pool_size`
32
+ (high, dry-run — replica change forces data movement), `pool_delete`
33
+ (high, dry-run — destroys all data).
34
+ - **RBD** — `rbd_ls`; `rbd_image_create` (med), `rbd_snapshot_create` (low),
35
+ `rbd_image_delete` (high, dry-run), `rbd_snapshot_delete` (high, dry-run).
36
+ - **CephFS / RGW** — `cephfs_status` (MDS ranks + "behind on trimming" +
37
+ client count), `rgw_status` (daemons + buckets + LARGE_OMAP /
38
+ unsharded-index findings).
39
+ - **Cluster-ops** — `mon_status` (quorum / out-of-quorum), `mgr_status`
40
+ (active/standbys/modules), `slow_ops` (blocked requests by OSD),
41
+ `capacity_forecast` (days-to-nearfull); `throttle_recovery` (med, undo —
42
+ `osd_max_backfills` / `osd_recovery_max_active`).
43
+ - **JWT authentication** — username + password exchanged for a short-lived JWT
44
+ at `POST /api/auth` against the mgr Dashboard (`https://<host>:8443`); the mgr
45
+ **dashboard** module must be enabled.
46
+ - **Encrypted secret store** — the Dashboard password is stored encrypted in
47
+ `~/.ceph-aiops/secrets.enc` (Fernet + scrypt); never plaintext on disk. Legacy
48
+ `CEPH_<TARGET>_PASSWORD` env var honoured as a fallback.
49
+ - **CLI** (`ceph-aiops`) — `init` wizard, `secret` management, `doctor`,
50
+ `overview`, and the `health` / `osd` sub-commands.
51
+ - **Teaching connection layer** — JWT login with centralised, human-readable
52
+ error translation (e.g. dashboard-module-not-enabled, auth failure).
53
+
54
+ ### Known limitations
55
+
56
+ - Preview / mock-only: multi-node rebalance behaviour and the write ops are
57
+ unverified against a real Ceph cluster. Fastest live check: a single-node
58
+ MicroCeph running `ceph-aiops doctor`.
59
+ - The ceph-mgr Dashboard API has no ETag / pagination, so this tool exposes none.
60
+ - Out of scope by design (v0.1.0): RGW multisite, NFS-Ganesha exports, and
61
+ cephadm orchestrator host management.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 wei <zhouwei008@gmail.com>
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,137 @@
1
+ Metadata-Version: 2.4
2
+ Name: ceph-aiops
3
+ Version: 0.1.0
4
+ Summary: Governed AI-ops for Ceph (ceph-mgr Dashboard REST): HEALTH_WARN root-cause analysis, OSD/PG/pool/RBD/CephFS/RGW operations, and destructive-op guardrails with a built-in governance harness (audit, budget, undo, risk tiers)
5
+ Author-email: wei <zhouwei008@gmail.com>
6
+ License-Expression: MIT
7
+ License-File: LICENSE
8
+ Requires-Python: >=3.11
9
+ Requires-Dist: cryptography>=42.0
10
+ Requires-Dist: httpx<1.0,>=0.27
11
+ Requires-Dist: mcp[cli]<2.0,>=1.10
12
+ Requires-Dist: pyyaml<7.0,>=6.0
13
+ Requires-Dist: rich<16.0,>=13.0
14
+ Requires-Dist: typer<1.0,>=0.12
15
+ Description-Content-Type: text/markdown
16
+
17
+ <!-- mcp-name: io.github.AIops-tools/ceph-aiops -->
18
+
19
+ # Ceph AIops (preview)
20
+
21
+ > **Disclaimer**: Community-maintained open-source project. **Not affiliated with, endorsed by, or sponsored by the Ceph project or any storage vendor.** Product and trademark names belong to their owners. MIT licensed.
22
+
23
+ Governed AI-ops for **Ceph** — talks to a vanilla **ceph-mgr Dashboard REST API**
24
+ (HTTPS `:8443`, username + password exchanged for a short-lived JWT at
25
+ `POST /api/auth`) with a **built-in governance harness**: unified audit log,
26
+ policy engine, token/runaway budget guard, undo-token recording, and
27
+ graduated-autonomy risk tiers. Works against stock ceph-mgr — **cephadm**,
28
+ **Proxmox-hosted Ceph**, or **MicroCeph** — with **no croit and no Kubernetes
29
+ dependency**. Self-contained: no external skill-family dependency.
30
+ **Preview — mock-validated only, not yet verified against a live cluster.**
31
+
32
+ ## What it does
33
+
34
+ The flagship analysis, plus the guarded reads and writes around it:
35
+
36
+ - **`cluster_health` — HEALTH_WARN/ERR root-cause analysis.** Instead of echoing
37
+ raw check codes (`PG_DEGRADED`, `OSD_NEARFULL`, `SLOW_OPS`, `MON_DOWN`,
38
+ `LARGE_OMAP_OBJECTS`, …), it turns each *active* check into plain language:
39
+ **what it means, the likely cause, and the suggested next action**. This is the
40
+ differentiator vs the hobby Ceph MCPs that just proxy `ceph -s`.
41
+ - **Governed destructive ops.** The operations operators actually fear —
42
+ `osd_purge`, `pool_delete`, `set_pool_size`, `rbd_image_delete` — carry
43
+ **dry-run + double-confirm** and a **high** risk tier; reversible tuning
44
+ (`osd_reweight`, `throttle_recovery`, `cluster_flag_set`, pool quota/pg_num/
45
+ autoscale) records an **undo descriptor** capturing the prior state.
46
+
47
+ ## What works
48
+
49
+ - **CLI** (`ceph-aiops ...`): `init`, `overview`, `health detail`/`health status`,
50
+ `osd tree/df/reweight/out/purge`, `secret set/list/rm/migrate/rotate-password`,
51
+ `doctor`, `mcp`. `osd out` and `osd purge` require `--dry-run` + double confirm.
52
+ - **MCP server** (`ceph-aiops mcp` or `ceph-aiops-mcp`): the full **35 tools**
53
+ (17 read, 18 write), every one wrapped with the bundled `@governed_tool`
54
+ harness. The CLI is a convenience subset; the MCP surface is the whole tool.
55
+ - **Encrypted credentials**: the Dashboard password lives in an encrypted store
56
+ `~/.ceph-aiops/secrets.enc` (Fernet + scrypt) — **never plaintext on disk**.
57
+ Unlock with a master password from `CEPH_AIOPS_MASTER_PASSWORD` (MCP/CI) or an
58
+ interactive prompt (CLI).
59
+ - **Reversibility**: reversible writes capture the prior state and record an
60
+ inverse undo descriptor (e.g. `osd_reweight` → prior weight, `set_pool_quota`
61
+ → prior quota, `throttle_recovery` → prior backfill/recovery settings).
62
+ - **Safety**: destructive ops (`osd_purge`, `osd_mark_out`, `pool_delete`,
63
+ `set_pool_size`, `rbd_image_delete`, `rbd_snapshot_delete`) are `high` risk
64
+ with `dry_run` and CLI double confirmation.
65
+
66
+ ## Capability matrix (35 MCP tools)
67
+
68
+ | Group | Tools | Count | R/W |
69
+ |-------|-------|:-----:|:---:|
70
+ | **Health** | `cluster_health` (flagship RCA), `cluster_status` | 2 | read |
71
+ | **OSD** | `osd_tree`, `osd_df`, `osd_perf` | 3 | read |
72
+ | | `cluster_flag_set` (low, undo), `osd_reweight` (med, undo), `osd_mark_in` (med, undo) | 3 | write |
73
+ | | `osd_mark_out` (high, dry-run), `osd_purge` (high, dry-run) | 2 | write |
74
+ | **PG** | `pg_summary`, `pg_dump_stuck`, `scrub_status` | 3 | read |
75
+ | | `trigger_scrub` (low), `trigger_deep_scrub` (low) | 2 | write |
76
+ | **Pool** | `pool_ls`, `pool_df` | 2 | read |
77
+ | | `set_pool_quota` (med, undo), `set_pool_pg_num` (med, undo), `set_pool_autoscale` (med, undo), `pool_create` (med) | 4 | write |
78
+ | | `set_pool_size` (high, dry-run), `pool_delete` (high, dry-run) | 2 | write |
79
+ | **RBD** | `rbd_ls` | 1 | read |
80
+ | | `rbd_image_create` (med), `rbd_snapshot_create` (low) | 2 | write |
81
+ | | `rbd_image_delete` (high, dry-run), `rbd_snapshot_delete` (high, dry-run) | 2 | write |
82
+ | **CephFS / RGW** | `cephfs_status`, `rgw_status` | 2 | read |
83
+ | **Cluster-ops** | `mon_status`, `mgr_status`, `slow_ops`, `capacity_forecast` | 4 | read |
84
+ | | `throttle_recovery` (med, undo) | 1 | write |
85
+
86
+ Totals: **35 tools — 17 read, 18 write.**
87
+
88
+ ## Quick start
89
+
90
+ ```bash
91
+ uv tool install ceph-aiops # or: pipx install ceph-aiops
92
+ ceph-aiops init # wizard: add a mgr target + store the Dashboard password (encrypted)
93
+ ceph-aiops doctor # JWT login + mgr-dashboard reachability
94
+ ceph-aiops overview # HEALTH status + active checks + OSD up/in
95
+ ceph-aiops health detail # decode the active HEALTH_WARN/ERR checks (RCA)
96
+ ceph-aiops osd df # per-OSD utilization, most-full first, near/backfill-full flags
97
+ ```
98
+
99
+ Run as an MCP server (stdio):
100
+
101
+ ```bash
102
+ export CEPH_AIOPS_MASTER_PASSWORD=... # unlock secrets non-interactively
103
+ ceph-aiops-mcp
104
+ ```
105
+
106
+ ## Governance
107
+
108
+ Every MCP tool passes through the bundled `@governed_tool` harness:
109
+
110
+ - **Audit** — every call (params, result, status, duration, risk tier,
111
+ approver, rationale) is logged to `~/.ceph-aiops/audit.db` (relocatable
112
+ via `CEPH_AIOPS_HOME`).
113
+ - **Budget / runaway guard** — token and call budgets trip a circuit breaker.
114
+ - **Risk tiers** — graduated autonomy; high-risk ops (purge/delete/replica
115
+ change) can require a named approver
116
+ (`CEPH_AUDIT_APPROVED_BY` / `CEPH_AUDIT_RATIONALE`).
117
+ - **Undo recording** — reversible writes record an inverse descriptor.
118
+
119
+ ## Supported scope & limitations
120
+
121
+ - **Deployments**: vanilla ceph-mgr with the **dashboard** module enabled —
122
+ cephadm, Proxmox-hosted Ceph, or MicroCeph. **No croit, no Kubernetes
123
+ dependency.**
124
+ - **Ceph has no ETag / pagination** on the Dashboard API, so this tool exposes
125
+ none — nothing is missing, the upstream API simply doesn't offer them.
126
+ - **Preview / mock-only.** Behaviour is validated against mocked Dashboard
127
+ responses. The cheapest **live** check is a single-node **MicroCeph**
128
+ (`snap install microceph` → bootstrap → loop-file OSDs) running
129
+ `ceph-aiops doctor`; a 3-node Vagrant cluster exercises real rebalance
130
+ behaviour. Multi-node rebalance and the write ops are **unverified against a
131
+ real cluster**.
132
+
133
+ ## Missing a capability?
134
+
135
+ RGW multisite, per-daemon config sprawl, NFS-Ganesha exports, orchestrator
136
+ (cephadm) host management — not here yet. **Open an issue or send a PR** — feedback
137
+ and contributions are welcome.
@@ -0,0 +1,121 @@
1
+ <!-- mcp-name: io.github.AIops-tools/ceph-aiops -->
2
+
3
+ # Ceph AIops (preview)
4
+
5
+ > **Disclaimer**: Community-maintained open-source project. **Not affiliated with, endorsed by, or sponsored by the Ceph project or any storage vendor.** Product and trademark names belong to their owners. MIT licensed.
6
+
7
+ Governed AI-ops for **Ceph** — talks to a vanilla **ceph-mgr Dashboard REST API**
8
+ (HTTPS `:8443`, username + password exchanged for a short-lived JWT at
9
+ `POST /api/auth`) with a **built-in governance harness**: unified audit log,
10
+ policy engine, token/runaway budget guard, undo-token recording, and
11
+ graduated-autonomy risk tiers. Works against stock ceph-mgr — **cephadm**,
12
+ **Proxmox-hosted Ceph**, or **MicroCeph** — with **no croit and no Kubernetes
13
+ dependency**. Self-contained: no external skill-family dependency.
14
+ **Preview — mock-validated only, not yet verified against a live cluster.**
15
+
16
+ ## What it does
17
+
18
+ The flagship analysis, plus the guarded reads and writes around it:
19
+
20
+ - **`cluster_health` — HEALTH_WARN/ERR root-cause analysis.** Instead of echoing
21
+ raw check codes (`PG_DEGRADED`, `OSD_NEARFULL`, `SLOW_OPS`, `MON_DOWN`,
22
+ `LARGE_OMAP_OBJECTS`, …), it turns each *active* check into plain language:
23
+ **what it means, the likely cause, and the suggested next action**. This is the
24
+ differentiator vs the hobby Ceph MCPs that just proxy `ceph -s`.
25
+ - **Governed destructive ops.** The operations operators actually fear —
26
+ `osd_purge`, `pool_delete`, `set_pool_size`, `rbd_image_delete` — carry
27
+ **dry-run + double-confirm** and a **high** risk tier; reversible tuning
28
+ (`osd_reweight`, `throttle_recovery`, `cluster_flag_set`, pool quota/pg_num/
29
+ autoscale) records an **undo descriptor** capturing the prior state.
30
+
31
+ ## What works
32
+
33
+ - **CLI** (`ceph-aiops ...`): `init`, `overview`, `health detail`/`health status`,
34
+ `osd tree/df/reweight/out/purge`, `secret set/list/rm/migrate/rotate-password`,
35
+ `doctor`, `mcp`. `osd out` and `osd purge` require `--dry-run` + double confirm.
36
+ - **MCP server** (`ceph-aiops mcp` or `ceph-aiops-mcp`): the full **35 tools**
37
+ (17 read, 18 write), every one wrapped with the bundled `@governed_tool`
38
+ harness. The CLI is a convenience subset; the MCP surface is the whole tool.
39
+ - **Encrypted credentials**: the Dashboard password lives in an encrypted store
40
+ `~/.ceph-aiops/secrets.enc` (Fernet + scrypt) — **never plaintext on disk**.
41
+ Unlock with a master password from `CEPH_AIOPS_MASTER_PASSWORD` (MCP/CI) or an
42
+ interactive prompt (CLI).
43
+ - **Reversibility**: reversible writes capture the prior state and record an
44
+ inverse undo descriptor (e.g. `osd_reweight` → prior weight, `set_pool_quota`
45
+ → prior quota, `throttle_recovery` → prior backfill/recovery settings).
46
+ - **Safety**: destructive ops (`osd_purge`, `osd_mark_out`, `pool_delete`,
47
+ `set_pool_size`, `rbd_image_delete`, `rbd_snapshot_delete`) are `high` risk
48
+ with `dry_run` and CLI double confirmation.
49
+
50
+ ## Capability matrix (35 MCP tools)
51
+
52
+ | Group | Tools | Count | R/W |
53
+ |-------|-------|:-----:|:---:|
54
+ | **Health** | `cluster_health` (flagship RCA), `cluster_status` | 2 | read |
55
+ | **OSD** | `osd_tree`, `osd_df`, `osd_perf` | 3 | read |
56
+ | | `cluster_flag_set` (low, undo), `osd_reweight` (med, undo), `osd_mark_in` (med, undo) | 3 | write |
57
+ | | `osd_mark_out` (high, dry-run), `osd_purge` (high, dry-run) | 2 | write |
58
+ | **PG** | `pg_summary`, `pg_dump_stuck`, `scrub_status` | 3 | read |
59
+ | | `trigger_scrub` (low), `trigger_deep_scrub` (low) | 2 | write |
60
+ | **Pool** | `pool_ls`, `pool_df` | 2 | read |
61
+ | | `set_pool_quota` (med, undo), `set_pool_pg_num` (med, undo), `set_pool_autoscale` (med, undo), `pool_create` (med) | 4 | write |
62
+ | | `set_pool_size` (high, dry-run), `pool_delete` (high, dry-run) | 2 | write |
63
+ | **RBD** | `rbd_ls` | 1 | read |
64
+ | | `rbd_image_create` (med), `rbd_snapshot_create` (low) | 2 | write |
65
+ | | `rbd_image_delete` (high, dry-run), `rbd_snapshot_delete` (high, dry-run) | 2 | write |
66
+ | **CephFS / RGW** | `cephfs_status`, `rgw_status` | 2 | read |
67
+ | **Cluster-ops** | `mon_status`, `mgr_status`, `slow_ops`, `capacity_forecast` | 4 | read |
68
+ | | `throttle_recovery` (med, undo) | 1 | write |
69
+
70
+ Totals: **35 tools — 17 read, 18 write.**
71
+
72
+ ## Quick start
73
+
74
+ ```bash
75
+ uv tool install ceph-aiops # or: pipx install ceph-aiops
76
+ ceph-aiops init # wizard: add a mgr target + store the Dashboard password (encrypted)
77
+ ceph-aiops doctor # JWT login + mgr-dashboard reachability
78
+ ceph-aiops overview # HEALTH status + active checks + OSD up/in
79
+ ceph-aiops health detail # decode the active HEALTH_WARN/ERR checks (RCA)
80
+ ceph-aiops osd df # per-OSD utilization, most-full first, near/backfill-full flags
81
+ ```
82
+
83
+ Run as an MCP server (stdio):
84
+
85
+ ```bash
86
+ export CEPH_AIOPS_MASTER_PASSWORD=... # unlock secrets non-interactively
87
+ ceph-aiops-mcp
88
+ ```
89
+
90
+ ## Governance
91
+
92
+ Every MCP tool passes through the bundled `@governed_tool` harness:
93
+
94
+ - **Audit** — every call (params, result, status, duration, risk tier,
95
+ approver, rationale) is logged to `~/.ceph-aiops/audit.db` (relocatable
96
+ via `CEPH_AIOPS_HOME`).
97
+ - **Budget / runaway guard** — token and call budgets trip a circuit breaker.
98
+ - **Risk tiers** — graduated autonomy; high-risk ops (purge/delete/replica
99
+ change) can require a named approver
100
+ (`CEPH_AUDIT_APPROVED_BY` / `CEPH_AUDIT_RATIONALE`).
101
+ - **Undo recording** — reversible writes record an inverse descriptor.
102
+
103
+ ## Supported scope & limitations
104
+
105
+ - **Deployments**: vanilla ceph-mgr with the **dashboard** module enabled —
106
+ cephadm, Proxmox-hosted Ceph, or MicroCeph. **No croit, no Kubernetes
107
+ dependency.**
108
+ - **Ceph has no ETag / pagination** on the Dashboard API, so this tool exposes
109
+ none — nothing is missing, the upstream API simply doesn't offer them.
110
+ - **Preview / mock-only.** Behaviour is validated against mocked Dashboard
111
+ responses. The cheapest **live** check is a single-node **MicroCeph**
112
+ (`snap install microceph` → bootstrap → loop-file OSDs) running
113
+ `ceph-aiops doctor`; a 3-node Vagrant cluster exercises real rebalance
114
+ behaviour. Multi-node rebalance and the write ops are **unverified against a
115
+ real cluster**.
116
+
117
+ ## Missing a capability?
118
+
119
+ RGW multisite, per-daemon config sprawl, NFS-Ganesha exports, orchestrator
120
+ (cephadm) host management — not here yet. **Open an issue or send a PR** — feedback
121
+ and contributions are welcome.
@@ -0,0 +1,57 @@
1
+ # Ceph AIops v0.1.0 — preview
2
+
3
+ Governed AI-ops for **Ceph** via the **ceph-mgr Dashboard REST API** for AI
4
+ agents, with a built-in governance harness (audit, policy, token/runaway
5
+ budget, undo-token recording, graduated risk tiers) and an encrypted credential
6
+ store. Standalone — no external skill-family dependency. Works against vanilla
7
+ ceph-mgr (cephadm / Proxmox-hosted / MicroCeph) — no croit, no Kubernetes.
8
+
9
+ > **Preview / mock-only.** All behaviour is validated against mocked Dashboard
10
+ > REST responses; it has not been run against a live Ceph cluster. The fastest
11
+ > live check is a single-node MicroCeph running `ceph-aiops doctor`.
12
+
13
+ ## Highlights
14
+
15
+ - **35 MCP tools** (17 read, 18 write), every one wrapped with `@governed_tool`:
16
+ - **Health** — `cluster_health` (flagship: per active HEALTH_WARN/ERR check →
17
+ plain-language cause + suggested action), `cluster_status`.
18
+ - **OSD** — `osd_tree`, `osd_df` (most-full first + near/backfill-full flags),
19
+ `osd_perf`; writes `cluster_flag_set`, `osd_reweight`, `osd_mark_in`,
20
+ `osd_mark_out` (high), `osd_purge` (high).
21
+ - **PG** — `pg_summary`, `pg_dump_stuck`, `scrub_status`; `trigger_scrub`,
22
+ `trigger_deep_scrub`.
23
+ - **Pool** — `pool_ls`, `pool_df` (usable capacity = raw ÷ size); writes
24
+ `set_pool_quota`, `set_pool_pg_num`, `set_pool_autoscale`, `pool_create`,
25
+ `set_pool_size` (high), `pool_delete` (high).
26
+ - **RBD** — `rbd_ls`; `rbd_image_create`, `rbd_snapshot_create`,
27
+ `rbd_image_delete` (high), `rbd_snapshot_delete` (high).
28
+ - **CephFS / RGW** — `cephfs_status`, `rgw_status`.
29
+ - **Cluster-ops** — `mon_status`, `mgr_status`, `slow_ops`,
30
+ `capacity_forecast`; `throttle_recovery` (the #1 tuning ask —
31
+ `osd_max_backfills` / `osd_recovery_max_active`).
32
+ - **HEALTH_WARN root-cause analysis** — `cluster_health` decodes each active
33
+ check code into cause + action, the differentiator vs raw `ceph -s` proxies.
34
+ - **JWT auth** — username + password exchanged for a short-lived JWT at
35
+ `POST /api/auth`; the mgr **dashboard** module must be enabled.
36
+ - **Encrypted secret store** (`~/.ceph-aiops/secrets.enc`, Fernet + scrypt) —
37
+ never plaintext on disk; legacy `CEPH_<TARGET>_PASSWORD` env fallback.
38
+ - **CLI** with an `init` onboarding wizard, `secret` management, and `doctor`.
39
+ - **Dry-run + double-confirm** on the destructive ops operators fear
40
+ (`osd_purge`, `osd_mark_out`, `pool_delete`, `set_pool_size`,
41
+ `rbd_image_delete`); reversible writes record an undo descriptor.
42
+
43
+ ## Install
44
+
45
+ ```bash
46
+ uv tool install ceph-aiops
47
+ ceph-aiops init
48
+ ceph-aiops doctor
49
+ ```
50
+
51
+ ## Caveats
52
+
53
+ - Preview / mock-only: multi-node rebalance behaviour and the write ops are
54
+ unverified against a real cluster.
55
+ - The Dashboard API has no ETag / pagination, so this tool exposes none.
56
+ - Out of scope for v0.1.0: RGW multisite, NFS-Ganesha exports, and cephadm
57
+ orchestrator host management.
@@ -0,0 +1,79 @@
1
+ # Security Policy
2
+
3
+ ## Disclaimer
4
+
5
+ Community-maintained open-source project. **Not affiliated with, endorsed by, or
6
+ sponsored by the Ceph project or the Ceph Foundation.** Product and trademark
7
+ names belong to their owners. Source is publicly auditable under the MIT license.
8
+
9
+ ## Reporting Vulnerabilities
10
+
11
+ Report privately via a GitHub Security Advisory on
12
+ [github.com/AIops-tools/Ceph-AIops](https://github.com/AIops-tools/Ceph-AIops/security/advisories)
13
+ or email zhouwei008@gmail.com. Please do not open public issues for security
14
+ reports.
15
+
16
+ ## Security Design
17
+
18
+ ### Credential Management
19
+ - Per-target ceph-mgr Dashboard passwords live **encrypted** in
20
+ `~/.ceph-aiops/secrets.enc` (Fernet/AES-128 + scrypt-derived key; chmod
21
+ 600), never in `config.yaml` and never in source. The master password is
22
+ never stored — only a per-store random salt and the ciphertext are on disk.
23
+ - A legacy plaintext env var `CEPH_<TARGET_NAME_UPPER>_PASSWORD` is still
24
+ honoured as a fallback with a deprecation warning (migrate with
25
+ `ceph-aiops secret migrate`).
26
+ - The password is exchanged for a short-lived **JWT** at `POST /api/auth`; only
27
+ the token is sent on subsequent requests (Bearer), and it is refreshed once on
28
+ a 401. The password is held only in memory, never logged or echoed; the config
29
+ file holds only host, port, username, and TLS settings.
30
+
31
+ ### Governed Operations
32
+ Every MCP tool runs through the bundled `@governed_tool` harness
33
+ (`ceph_aiops.governance`):
34
+ - **Audit** — every call logged to a local SQLite DB under `~/.ceph-aiops/`
35
+ (relocatable via `CEPH_AIOPS_HOME`), agent-attributed, secret-redacted.
36
+ - **Token/runaway budget** — hard ceilings (`CEPH_MAX_TOOL_CALLS` /
37
+ `CEPH_MAX_TOOL_SECONDS`) plus an on-by-default guard that trips a tight
38
+ poll/retry loop, preventing unbounded API consumption (e.g. polling a slow
39
+ session).
40
+ - **Graduated risk tiers** — `~/.ceph-aiops/rules.yaml` `risk_tiers` gate
41
+ writes by environment/tag; the highest tiers require a recorded approver.
42
+ - **Undo-token recording** — reversible writes capture the BEFORE state and
43
+ record an inverse descriptor (e.g. `osd_reweight`→restore prior weight,
44
+ `cluster_flag_set`→toggle the flag back, `throttle_recovery`→restore prior
45
+ backfill/recovery limits) so the change can be rolled back.
46
+
47
+ ### State-Changing Operations
48
+ Destructive writes — `osd_mark_out`, `osd_purge`, `set_pool_size`, `pool_delete`,
49
+ `rbd_image_delete`, `rbd_snapshot_delete` — are `risk_level=high`, accept a
50
+ `dry_run` preview, and (under `risk_tiers`) require a recorded approver
51
+ (`CEPH_AUDIT_APPROVED_BY` + `CEPH_AUDIT_RATIONALE`). The CLI additionally
52
+ double-confirms `osd out` and `osd purge` and supports `--dry-run`. Reversible
53
+ medium/low writes capture before-state and, where a safe inverse exists, record
54
+ an undo token. Ceph has no ETag/If-Match and its list endpoints return full
55
+ arrays, so there is no optimistic-concurrency token to manage.
56
+
57
+ ### SSL/TLS Verification
58
+ `verify_ssl` defaults to true; disable only for self-signed lab certificates.
59
+
60
+ ### Prompt-Injection Protection
61
+ All server-returned text (pool/OSD names, PG ids, health check messages, RGW
62
+ bucket names) is passed through a `sanitize()` truncate + control-character strip
63
+ before reaching the agent.
64
+
65
+ ### Network Scope
66
+ No webhooks, no telemetry, no outbound calls beyond the configured ceph-mgr
67
+ Dashboard REST API endpoint. No post-install scripts or background services.
68
+
69
+ ## Static Analysis
70
+
71
+ ```bash
72
+ uvx bandit -r ceph_aiops/ mcp_server/
73
+ uv run ruff check .
74
+ ```
75
+
76
+ ## Supported Versions
77
+
78
+ The latest released version receives security fixes. This is a preview (0.x);
79
+ pin a version in production.
@@ -0,0 +1,9 @@
1
+ """ceph-aiops — governed Ceph SCALE operations for AI agents.
2
+
3
+ Standalone and self-contained: the governance harness (audit, token budget,
4
+ undo-token recording, graduated risk tiers, prompt-injection sanitize) is
5
+ bundled under ``ceph_aiops.governance`` — this package has no external
6
+ skill-family dependency. Preview: not yet full-coverage.
7
+ """
8
+
9
+ __version__ = "0.1.0"
@@ -0,0 +1,9 @@
1
+ """CLI package for ceph-aiops.
2
+
3
+ Re-exports ``app`` so the pyproject entry point
4
+ ``ceph-aiops = "ceph_aiops.cli:app"`` works unchanged.
5
+ """
6
+
7
+ from ceph_aiops.cli._root import app
8
+
9
+ __all__ = ["app"]
@@ -0,0 +1,78 @@
1
+ """Shared helpers for ceph-aiops CLI sub-modules."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import functools
6
+ from collections.abc import Callable
7
+ from pathlib import Path
8
+ from typing import Annotated, Any
9
+
10
+ import typer
11
+ from rich.console import Console
12
+
13
+ console = Console()
14
+
15
+ # ─── Shared Option types ───────────────────────────────────────────────────
16
+
17
+ TargetOption = Annotated[
18
+ str | None, typer.Option("--target", "-t", help="Target name from config")
19
+ ]
20
+ DryRunOption = Annotated[
21
+ bool, typer.Option("--dry-run", help="Print the API call without executing")
22
+ ]
23
+
24
+
25
+ def _cli_error_types() -> tuple[type[BaseException], ...]:
26
+ """Exceptions translated to a one-line teaching error instead of a traceback."""
27
+ from ceph_aiops.connection import CephApiError
28
+
29
+ return (CephApiError, KeyError, OSError, ValueError)
30
+
31
+
32
+ def cli_errors(fn: Callable) -> Callable:
33
+ """Translate known exceptions into one red line + exit code 1."""
34
+
35
+ @functools.wraps(fn)
36
+ def wrapper(*args: Any, **kwargs: Any) -> Any:
37
+ try:
38
+ return fn(*args, **kwargs)
39
+ except (typer.Exit, typer.Abort):
40
+ raise
41
+ except _cli_error_types() as e:
42
+ message = str(e)
43
+ if isinstance(e, KeyError):
44
+ message = f"Missing required key or environment variable: {message}"
45
+ console.print(f"[red]Error: {message}[/]")
46
+ raise typer.Exit(1) from e
47
+
48
+ return wrapper
49
+
50
+
51
+ def get_connection(target: str | None, config_path: Path | None = None):
52
+ """Return a (conn, config) tuple for the given target."""
53
+ from ceph_aiops.config import load_config
54
+ from ceph_aiops.connection import ConnectionManager
55
+
56
+ cfg = load_config(config_path)
57
+ mgr = ConnectionManager(cfg)
58
+ return mgr.connect(target), cfg
59
+
60
+
61
+ def dry_run_print(*, operation: str, api_call: str, parameters: dict | None = None) -> None:
62
+ """Print a dry-run preview of the API call that would be made."""
63
+ console.print("\n[bold magenta][DRY-RUN] No changes will be made.[/]")
64
+ console.print(f"[magenta] Operation: {operation}[/]")
65
+ console.print(f"[magenta] API Call: {api_call}[/]")
66
+ for k, v in (parameters or {}).items():
67
+ console.print(f"[magenta] Param: {k} = {v}[/]")
68
+ console.print("[magenta] Run without --dry-run to execute.[/]\n")
69
+
70
+
71
+ def double_confirm(action: str, resource: str) -> None:
72
+ """Require two confirmations for a destructive operation."""
73
+ console.print(f"[bold yellow]⚠️ About to: {action} '{resource}'[/]")
74
+ typer.confirm(f"Confirm 1/2: {action} '{resource}'?", abort=True)
75
+ typer.confirm(
76
+ f"Confirm 2/2: really {action} '{resource}'? This may be irreversible.",
77
+ abort=True,
78
+ )
@@ -0,0 +1,57 @@
1
+ """Top-level Typer app: assembles sub-apps and top-level commands."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import typer
6
+
7
+ from ceph_aiops.cli._common import cli_errors
8
+ from ceph_aiops.cli.doctor import doctor_cmd
9
+ from ceph_aiops.cli.health import health_app
10
+ from ceph_aiops.cli.init import init_cmd
11
+ from ceph_aiops.cli.osd import osd_app
12
+ from ceph_aiops.cli.overview import overview_cmd
13
+ from ceph_aiops.cli.secret import secret_app
14
+
15
+ app = typer.Typer(
16
+ name="ceph-aiops",
17
+ help="Governed AI-ops for Ceph (mgr Dashboard REST): health RCA, OSD/PG/pool, "
18
+ "RBD/CephFS/RGW, recovery, capacity.",
19
+ no_args_is_help=True,
20
+ )
21
+
22
+ app.add_typer(health_app, name="health")
23
+ app.add_typer(osd_app, name="osd")
24
+ app.add_typer(secret_app, name="secret")
25
+ app.command("init")(init_cmd)
26
+ app.command("overview")(overview_cmd)
27
+ app.command("doctor")(doctor_cmd)
28
+
29
+
30
+ @app.command("mcp")
31
+ @cli_errors
32
+ def mcp_cmd() -> None:
33
+ """Start the MCP server (stdio transport).
34
+
35
+ Single-command entry point for MCP clients (does not go through uvx/PyPI
36
+ resolution at launch):
37
+ ceph-aiops mcp
38
+ """
39
+ import sys
40
+
41
+ if sys.version_info < (3, 11):
42
+ typer.echo(
43
+ f"ERROR: ceph-aiops requires Python >= 3.11 "
44
+ f"(got {sys.version_info.major}.{sys.version_info.minor}).\n"
45
+ f"Fix: uv python install 3.12 && "
46
+ f"uv tool install --python 3.12 --force ceph-aiops",
47
+ err=True,
48
+ )
49
+ raise typer.Exit(2)
50
+
51
+ from mcp_server.server import main as _mcp_main
52
+
53
+ _mcp_main()
54
+
55
+
56
+ if __name__ == "__main__":
57
+ app()
@@ -0,0 +1,21 @@
1
+ """Doctor top-level command: environment and connectivity check."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Annotated
6
+
7
+ import typer
8
+
9
+ from ceph_aiops.cli._common import cli_errors
10
+
11
+
12
+ @cli_errors
13
+ def doctor_cmd(
14
+ skip_auth: Annotated[
15
+ bool, typer.Option("--skip-auth", help="Skip connectivity check (faster)")
16
+ ] = False,
17
+ ) -> None:
18
+ """Check environment, config, secrets, and connectivity."""
19
+ from ceph_aiops.doctor import run_doctor
20
+
21
+ raise typer.Exit(run_doctor(skip_auth=skip_auth))