nutanix-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 (72) hide show
  1. nutanix_aiops-0.1.0/.gitignore +7 -0
  2. nutanix_aiops-0.1.0/CHANGELOG.md +61 -0
  3. nutanix_aiops-0.1.0/LICENSE +21 -0
  4. nutanix_aiops-0.1.0/PKG-INFO +136 -0
  5. nutanix_aiops-0.1.0/README.md +120 -0
  6. nutanix_aiops-0.1.0/RELEASE_NOTES.md +58 -0
  7. nutanix_aiops-0.1.0/SECURITY.md +81 -0
  8. nutanix_aiops-0.1.0/mcp_server/__init__.py +1 -0
  9. nutanix_aiops-0.1.0/mcp_server/_shared.py +100 -0
  10. nutanix_aiops-0.1.0/mcp_server/server.py +39 -0
  11. nutanix_aiops-0.1.0/mcp_server/tools/__init__.py +1 -0
  12. nutanix_aiops-0.1.0/mcp_server/tools/alerts.py +97 -0
  13. nutanix_aiops-0.1.0/mcp_server/tools/capacity.py +49 -0
  14. nutanix_aiops-0.1.0/mcp_server/tools/catalog.py +102 -0
  15. nutanix_aiops-0.1.0/mcp_server/tools/clusters.py +59 -0
  16. nutanix_aiops-0.1.0/mcp_server/tools/dataprotection.py +177 -0
  17. nutanix_aiops-0.1.0/mcp_server/tools/lcm.py +69 -0
  18. nutanix_aiops-0.1.0/mcp_server/tools/network.py +87 -0
  19. nutanix_aiops-0.1.0/mcp_server/tools/storage.py +120 -0
  20. nutanix_aiops-0.1.0/mcp_server/tools/vms.py +250 -0
  21. nutanix_aiops-0.1.0/nutanix_aiops/__init__.py +9 -0
  22. nutanix_aiops-0.1.0/nutanix_aiops/cli/__init__.py +9 -0
  23. nutanix_aiops-0.1.0/nutanix_aiops/cli/_common.py +78 -0
  24. nutanix_aiops-0.1.0/nutanix_aiops/cli/_root.py +57 -0
  25. nutanix_aiops-0.1.0/nutanix_aiops/cli/cluster.py +58 -0
  26. nutanix_aiops-0.1.0/nutanix_aiops/cli/doctor.py +21 -0
  27. nutanix_aiops-0.1.0/nutanix_aiops/cli/init.py +102 -0
  28. nutanix_aiops-0.1.0/nutanix_aiops/cli/overview.py +16 -0
  29. nutanix_aiops-0.1.0/nutanix_aiops/cli/secret.py +103 -0
  30. nutanix_aiops-0.1.0/nutanix_aiops/cli/vm.py +112 -0
  31. nutanix_aiops-0.1.0/nutanix_aiops/config.py +141 -0
  32. nutanix_aiops-0.1.0/nutanix_aiops/connection.py +247 -0
  33. nutanix_aiops-0.1.0/nutanix_aiops/doctor.py +86 -0
  34. nutanix_aiops-0.1.0/nutanix_aiops/governance/__init__.py +40 -0
  35. nutanix_aiops-0.1.0/nutanix_aiops/governance/audit.py +377 -0
  36. nutanix_aiops-0.1.0/nutanix_aiops/governance/budget.py +225 -0
  37. nutanix_aiops-0.1.0/nutanix_aiops/governance/decorators.py +474 -0
  38. nutanix_aiops-0.1.0/nutanix_aiops/governance/paths.py +23 -0
  39. nutanix_aiops-0.1.0/nutanix_aiops/governance/patterns.py +378 -0
  40. nutanix_aiops-0.1.0/nutanix_aiops/governance/policy.py +411 -0
  41. nutanix_aiops-0.1.0/nutanix_aiops/governance/sanitize.py +39 -0
  42. nutanix_aiops-0.1.0/nutanix_aiops/governance/undo.py +218 -0
  43. nutanix_aiops-0.1.0/nutanix_aiops/ops/__init__.py +1 -0
  44. nutanix_aiops-0.1.0/nutanix_aiops/ops/_util.py +42 -0
  45. nutanix_aiops-0.1.0/nutanix_aiops/ops/alerts.py +159 -0
  46. nutanix_aiops-0.1.0/nutanix_aiops/ops/capacity.py +88 -0
  47. nutanix_aiops-0.1.0/nutanix_aiops/ops/catalog.py +88 -0
  48. nutanix_aiops-0.1.0/nutanix_aiops/ops/clusters.py +94 -0
  49. nutanix_aiops-0.1.0/nutanix_aiops/ops/dataprotection.py +122 -0
  50. nutanix_aiops-0.1.0/nutanix_aiops/ops/lcm.py +73 -0
  51. nutanix_aiops-0.1.0/nutanix_aiops/ops/network.py +103 -0
  52. nutanix_aiops-0.1.0/nutanix_aiops/ops/overview.py +47 -0
  53. nutanix_aiops-0.1.0/nutanix_aiops/ops/storage.py +105 -0
  54. nutanix_aiops-0.1.0/nutanix_aiops/ops/vms.py +184 -0
  55. nutanix_aiops-0.1.0/nutanix_aiops/secretstore.py +302 -0
  56. nutanix_aiops-0.1.0/pyproject.toml +59 -0
  57. nutanix_aiops-0.1.0/server.json +21 -0
  58. nutanix_aiops-0.1.0/skills/nutanix-aiops/SKILL.md +117 -0
  59. nutanix_aiops-0.1.0/skills/nutanix-aiops/references/capabilities.md +120 -0
  60. nutanix_aiops-0.1.0/skills/nutanix-aiops/references/cli-reference.md +64 -0
  61. nutanix_aiops-0.1.0/skills/nutanix-aiops/references/setup-guide.md +104 -0
  62. nutanix_aiops-0.1.0/smithery.yaml +9 -0
  63. nutanix_aiops-0.1.0/tests/test_alerts.py +87 -0
  64. nutanix_aiops-0.1.0/tests/test_capacity.py +75 -0
  65. nutanix_aiops-0.1.0/tests/test_catalog.py +71 -0
  66. nutanix_aiops-0.1.0/tests/test_dataprotection.py +69 -0
  67. nutanix_aiops-0.1.0/tests/test_lcm.py +69 -0
  68. nutanix_aiops-0.1.0/tests/test_network.py +89 -0
  69. nutanix_aiops-0.1.0/tests/test_secretstore.py +99 -0
  70. nutanix_aiops-0.1.0/tests/test_smoke.py +312 -0
  71. nutanix_aiops-0.1.0/tests/test_storage.py +75 -0
  72. nutanix_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 nutanix-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 **Nutanix Prism Central** (v4 REST
9
+ API) with a bundled governance harness. **Mock-validated only — not yet verified
10
+ against a live Prism Central.**
11
+
12
+ ### Added
13
+
14
+ - **47 MCP tools** (21 read, 26 write), every one wrapped with the bundled
15
+ `@governed_tool` harness (audit, policy, token/runaway budget, undo,
16
+ risk-tiers):
17
+ - **Clusters** (read) — `cluster_list`, `cluster_health`, `host_list`,
18
+ `cluster_utilization`.
19
+ - **VMs** — `vm_list` (AHV + ESXi), `vm_get` (surfaces ETag); `vm_power_on`
20
+ (low), `vm_guest_shutdown` / `vm_power_off` / `vm_reboot` / `vm_create` /
21
+ `vm_update` (med, undo prior CPU/mem) / `vm_clone` (med); `vm_delete` and
22
+ `vm_migrate` (HIGH, dry-run; `vm_migrate` undo → prior host).
23
+ - **Storage** — `storage_container_list`; `storage_container_create` /
24
+ `_update` (med, undo prior); `storage_container_delete` (HIGH, dry-run).
25
+ - **Network** — `subnet_list`, `subnet_get` (ETag); `subnet_create` (med);
26
+ `subnet_delete` (HIGH, dry-run).
27
+ - **Catalog** — `image_list`; `image_delete` (HIGH, dry-run); `category_list`;
28
+ `category_create` (low); `category_assign` (med, bulk-assign to VMs).
29
+ - **Data protection / DR** — `snapshot_list`, `recovery_point_list`,
30
+ `protection_domain_list`; `snapshot_create` (low); `vm_protect` (med);
31
+ `snapshot_delete` / `snapshot_restore` / `pd_failover` (HIGH, dry-run).
32
+ - **Alerts** — `alert_list`, `event_list`, `audit_list`; `analyze_alert`
33
+ (RCA — correlates an alert with related events into a probable-cause +
34
+ suggested-actions summary); `alert_acknowledge` / `alert_resolve` (low).
35
+ - **LCM** — `lcm_inventory`; `lcm_precheck` (low); `lcm_update` (HIGH
36
+ firmware/software update, dry-run).
37
+ - **Capacity** — `task_list`; `capacity_runway` (days-to-full forecast).
38
+ - **Automatic ETag / If-Match** handling on every mutation and **automatic
39
+ pagination** on every list tool.
40
+ - **Mixed-hypervisor VM listing** — `vm_list` returns both AHV and ESXi guests.
41
+ - **Encrypted secret store** — the Prism Central password is stored encrypted in
42
+ `~/.nutanix-aiops/secrets.enc` (Fernet + scrypt); never plaintext on disk.
43
+ Legacy `NUTANIX_<TARGET>_PASSWORD` env var honoured as a fallback.
44
+ - **CLI** (`nutanix-aiops`) — `init` wizard, `secret` management, `doctor`
45
+ (connectivity + REST-RBAC preflight), `overview`, `mcp`, and the `cluster` /
46
+ `vm` sub-commands (`vm delete` / `vm migrate` with `--dry-run` + double
47
+ confirm).
48
+ - **HTTP Basic-auth REST connection layer** over Prism Central `:9440` with
49
+ centralised teaching error translation.
50
+
51
+ ### Known limitations
52
+
53
+ - Preview / mock-only: validated against mocked v4 responses; needs live
54
+ verification against a real Prism Central. Self-testable free on Nutanix
55
+ Community Edition (CE) + X-Small Prism Central.
56
+ - The **LCM update**, **PD failover**, and **ESXi-VM listing** paths in
57
+ particular are unverified against live systems.
58
+ - The Prism Central account needs REST API rights, not just Web UI access.
59
+ - Out of scope this release: IAM / users / roles, Files / Objects / Volumes
60
+ services, reports, X-Play playbooks, and anything outside Prism Central v4.
61
+ </content>
@@ -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,136 @@
1
+ Metadata-Version: 2.4
2
+ Name: nutanix-aiops
3
+ Version: 0.1.0
4
+ Summary: Governed AI-ops for Nutanix Prism Central (v4): cluster/VM/storage/network/DR/alert/LCM operations with automatic ETag & pagination handling and 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/nutanix-aiops -->
18
+
19
+ # Nutanix AIops (preview)
20
+
21
+ > **Disclaimer**: Community-maintained open-source project. **Not affiliated with, endorsed by, or sponsored by Nutanix.** Product and trademark names belong to their owners. MIT licensed.
22
+
23
+ Governed AI-ops for **Nutanix Prism Central** (v4 REST API) — clusters, hosts,
24
+ VMs (AHV + ESXi), storage, network, catalog, data protection / DR, alerts, LCM
25
+ upgrades, and capacity — with a **built-in governance harness**: unified audit
26
+ log, policy engine, token/runaway budget guard, undo-token recording, and
27
+ graduated-autonomy risk tiers. Connects to Prism Central on HTTPS `:9440` with
28
+ HTTP Basic auth (username + encrypted password). Self-contained: no dependencies
29
+ beyond `httpx` and the MCP SDK. **Preview — mock-validated only, not yet verified
30
+ against a live Prism Central.**
31
+
32
+ ## Why this over a read-only Nutanix MCP
33
+
34
+ - **Automatic ETag / If-Match** on every mutation. The v4 API rejects an update
35
+ or delete without the entity's current ETag — the classic footgun. This tool
36
+ fetches and sends `If-Match` for you.
37
+ - **Automatic pagination** — list tools return the full set, not just page one.
38
+ - **Mixed-hypervisor VM listing** — `vm_list` returns both **AHV** and **ESXi**
39
+ guests under the same Prism Central (built for Broadcom→Nutanix migration
40
+ estates).
41
+ - **Governance harness** — audit / token+call budget / risk-tier approval /
42
+ undo-token / prompt-injection sanitize, with **dry-run + double-confirm** on
43
+ destructive writes.
44
+
45
+ ## Capability matrix (47 MCP tools)
46
+
47
+ | Group | Tools | Count | R/W |
48
+ |-------|-------|:-----:|:---:|
49
+ | **Clusters** | `cluster_list`, `cluster_health`, `host_list`, `cluster_utilization` | 4 | 4 read |
50
+ | **VMs** | `vm_list`, `vm_get`, `vm_power_on`, `vm_guest_shutdown`, `vm_power_off`, `vm_reboot`, `vm_create`, `vm_update`, `vm_clone`, `vm_delete`, `vm_migrate` | 11 | 2 read · 9 write |
51
+ | **Storage** | `storage_container_list` / `_create` / `_update` / `_delete` | 4 | 1 read · 3 write |
52
+ | **Network** | `subnet_list`, `subnet_get`, `subnet_create`, `subnet_delete` | 4 | 2 read · 2 write |
53
+ | **Catalog** | `image_list`, `image_delete`, `category_list`, `category_create`, `category_assign` | 5 | 2 read · 3 write |
54
+ | **Data protection / DR** | `snapshot_list` / `_create` / `_delete` / `_restore`, `recovery_point_list`, `protection_domain_list`, `vm_protect`, `pd_failover` | 8 | 3 read · 5 write |
55
+ | **Alerts** | `alert_list`, `event_list`, `audit_list`, `analyze_alert` (RCA), `alert_acknowledge`, `alert_resolve` | 6 | 4 read · 2 write |
56
+ | **LCM (upgrades)** | `lcm_inventory`, `lcm_precheck`, `lcm_update` | 3 | 1 read · 2 write |
57
+ | **Capacity** | `task_list`, `capacity_runway` | 2 | 2 read |
58
+ | **Total** | | **47** | 21 read · 26 write |
59
+
60
+ `analyze_alert` is the flagship read: it correlates an alert with its related
61
+ events into a probable-cause + suggested-actions summary. High-risk writes
62
+ (`vm_delete`, `vm_migrate`, `storage_container_delete`, `subnet_delete`,
63
+ `snapshot_delete`, `snapshot_restore`, `pd_failover`, `image_delete`,
64
+ `lcm_update`) support `dry_run` and, at the CLI, double confirmation.
65
+
66
+ ## Install
67
+
68
+ ```bash
69
+ uv tool install nutanix-aiops # or: pipx install nutanix-aiops
70
+ ```
71
+
72
+ ## Quick start
73
+
74
+ ```bash
75
+ nutanix-aiops init # wizard: PC host / port 9440 / username / verify_ssl + encrypted password
76
+ nutanix-aiops doctor # config, secrets, connectivity + REST-RBAC preflight
77
+ nutanix-aiops overview # one-shot estate summary
78
+ nutanix-aiops vm list # AHV + ESXi VMs
79
+ ```
80
+
81
+ Run as an MCP server (stdio):
82
+
83
+ ```bash
84
+ export NUTANIX_AIOPS_MASTER_PASSWORD=... # unlock the encrypted secret store non-interactively
85
+ nutanix-aiops mcp
86
+ ```
87
+
88
+ ## CLI
89
+
90
+ `nutanix-aiops` (Typer): `init`, `overview`, `doctor`, `mcp`; `cluster
91
+ list/health/hosts/util`; `vm list/get/power/delete/migrate` (`delete` & `migrate`
92
+ take `--dry-run` + double confirm); `secret set/list/rm/migrate/rotate-password`.
93
+ The CLI is a convenience subset — the full 47-tool surface is via the MCP server.
94
+
95
+ ## Governance
96
+
97
+ Every MCP tool passes through the bundled `@governed_tool` harness:
98
+
99
+ - **Audit** — every call (params, result, status, duration, risk tier, approver,
100
+ rationale) is logged to `~/.nutanix-aiops/audit.db` (relocatable via
101
+ `NUTANIX_AIOPS_HOME`).
102
+ - **Budget / runaway guard** — token and call budgets trip a circuit breaker.
103
+ - **Risk tiers** — graduated autonomy; high-risk ops can require a named approver
104
+ (`NUTANIX_AUDIT_APPROVED_BY` / `NUTANIX_AUDIT_RATIONALE`).
105
+ - **Undo recording** — reversible writes record an inverse descriptor
106
+ (`vm_update` → prior CPU/memory, `vm_migrate` → prior host).
107
+
108
+ ## Credentials
109
+
110
+ The Prism Central password is stored **encrypted** in
111
+ `~/.nutanix-aiops/secrets.enc` (Fernet + scrypt) — never plaintext on disk.
112
+ Unlock with a master password from `NUTANIX_AIOPS_MASTER_PASSWORD` (MCP/CI) or an
113
+ interactive prompt (CLI). The non-secret connection details (host, port,
114
+ username, verify_ssl) live in `~/.nutanix-aiops/config.yaml`. A legacy plaintext
115
+ env var `NUTANIX_<TARGET>_PASSWORD` is honoured as a fallback.
116
+
117
+ > **Gotcha:** the Prism Central account needs **REST API** rights, not just Web
118
+ > UI access. `doctor`'s REST-RBAC preflight catches this early.
119
+
120
+ ## Supported scope & limitations
121
+
122
+ - **Preview / mock-only.** All behaviour is validated against mocked v4 REST
123
+ responses; it has not been run against a live Prism Central. The fastest live
124
+ check is `nutanix-aiops doctor`.
125
+ - **Self-testable free** on **Nutanix Community Edition (CE)**: a single-node CE
126
+ cluster + an X-Small Prism Central VM.
127
+ - **Least-verified paths:** LCM update (`lcm_update`), protection-domain failover
128
+ (`pd_failover`), and **ESXi-VM listing** in particular need live validation.
129
+ - **Out of scope this release:** IAM / users / roles, Files / Objects / Volumes
130
+ services, reports, X-Play playbooks, and anything outside Prism Central v4.
131
+
132
+ ## Missing a capability?
133
+
134
+ Missing a tool, an API dialect, or a workflow? **Open an issue or PR** —
135
+ feedback and contributions are welcome.
136
+ </content>
@@ -0,0 +1,120 @@
1
+ <!-- mcp-name: io.github.AIops-tools/nutanix-aiops -->
2
+
3
+ # Nutanix AIops (preview)
4
+
5
+ > **Disclaimer**: Community-maintained open-source project. **Not affiliated with, endorsed by, or sponsored by Nutanix.** Product and trademark names belong to their owners. MIT licensed.
6
+
7
+ Governed AI-ops for **Nutanix Prism Central** (v4 REST API) — clusters, hosts,
8
+ VMs (AHV + ESXi), storage, network, catalog, data protection / DR, alerts, LCM
9
+ upgrades, and capacity — with a **built-in governance harness**: unified audit
10
+ log, policy engine, token/runaway budget guard, undo-token recording, and
11
+ graduated-autonomy risk tiers. Connects to Prism Central on HTTPS `:9440` with
12
+ HTTP Basic auth (username + encrypted password). Self-contained: no dependencies
13
+ beyond `httpx` and the MCP SDK. **Preview — mock-validated only, not yet verified
14
+ against a live Prism Central.**
15
+
16
+ ## Why this over a read-only Nutanix MCP
17
+
18
+ - **Automatic ETag / If-Match** on every mutation. The v4 API rejects an update
19
+ or delete without the entity's current ETag — the classic footgun. This tool
20
+ fetches and sends `If-Match` for you.
21
+ - **Automatic pagination** — list tools return the full set, not just page one.
22
+ - **Mixed-hypervisor VM listing** — `vm_list` returns both **AHV** and **ESXi**
23
+ guests under the same Prism Central (built for Broadcom→Nutanix migration
24
+ estates).
25
+ - **Governance harness** — audit / token+call budget / risk-tier approval /
26
+ undo-token / prompt-injection sanitize, with **dry-run + double-confirm** on
27
+ destructive writes.
28
+
29
+ ## Capability matrix (47 MCP tools)
30
+
31
+ | Group | Tools | Count | R/W |
32
+ |-------|-------|:-----:|:---:|
33
+ | **Clusters** | `cluster_list`, `cluster_health`, `host_list`, `cluster_utilization` | 4 | 4 read |
34
+ | **VMs** | `vm_list`, `vm_get`, `vm_power_on`, `vm_guest_shutdown`, `vm_power_off`, `vm_reboot`, `vm_create`, `vm_update`, `vm_clone`, `vm_delete`, `vm_migrate` | 11 | 2 read · 9 write |
35
+ | **Storage** | `storage_container_list` / `_create` / `_update` / `_delete` | 4 | 1 read · 3 write |
36
+ | **Network** | `subnet_list`, `subnet_get`, `subnet_create`, `subnet_delete` | 4 | 2 read · 2 write |
37
+ | **Catalog** | `image_list`, `image_delete`, `category_list`, `category_create`, `category_assign` | 5 | 2 read · 3 write |
38
+ | **Data protection / DR** | `snapshot_list` / `_create` / `_delete` / `_restore`, `recovery_point_list`, `protection_domain_list`, `vm_protect`, `pd_failover` | 8 | 3 read · 5 write |
39
+ | **Alerts** | `alert_list`, `event_list`, `audit_list`, `analyze_alert` (RCA), `alert_acknowledge`, `alert_resolve` | 6 | 4 read · 2 write |
40
+ | **LCM (upgrades)** | `lcm_inventory`, `lcm_precheck`, `lcm_update` | 3 | 1 read · 2 write |
41
+ | **Capacity** | `task_list`, `capacity_runway` | 2 | 2 read |
42
+ | **Total** | | **47** | 21 read · 26 write |
43
+
44
+ `analyze_alert` is the flagship read: it correlates an alert with its related
45
+ events into a probable-cause + suggested-actions summary. High-risk writes
46
+ (`vm_delete`, `vm_migrate`, `storage_container_delete`, `subnet_delete`,
47
+ `snapshot_delete`, `snapshot_restore`, `pd_failover`, `image_delete`,
48
+ `lcm_update`) support `dry_run` and, at the CLI, double confirmation.
49
+
50
+ ## Install
51
+
52
+ ```bash
53
+ uv tool install nutanix-aiops # or: pipx install nutanix-aiops
54
+ ```
55
+
56
+ ## Quick start
57
+
58
+ ```bash
59
+ nutanix-aiops init # wizard: PC host / port 9440 / username / verify_ssl + encrypted password
60
+ nutanix-aiops doctor # config, secrets, connectivity + REST-RBAC preflight
61
+ nutanix-aiops overview # one-shot estate summary
62
+ nutanix-aiops vm list # AHV + ESXi VMs
63
+ ```
64
+
65
+ Run as an MCP server (stdio):
66
+
67
+ ```bash
68
+ export NUTANIX_AIOPS_MASTER_PASSWORD=... # unlock the encrypted secret store non-interactively
69
+ nutanix-aiops mcp
70
+ ```
71
+
72
+ ## CLI
73
+
74
+ `nutanix-aiops` (Typer): `init`, `overview`, `doctor`, `mcp`; `cluster
75
+ list/health/hosts/util`; `vm list/get/power/delete/migrate` (`delete` & `migrate`
76
+ take `--dry-run` + double confirm); `secret set/list/rm/migrate/rotate-password`.
77
+ The CLI is a convenience subset — the full 47-tool surface is via the MCP server.
78
+
79
+ ## Governance
80
+
81
+ Every MCP tool passes through the bundled `@governed_tool` harness:
82
+
83
+ - **Audit** — every call (params, result, status, duration, risk tier, approver,
84
+ rationale) is logged to `~/.nutanix-aiops/audit.db` (relocatable via
85
+ `NUTANIX_AIOPS_HOME`).
86
+ - **Budget / runaway guard** — token and call budgets trip a circuit breaker.
87
+ - **Risk tiers** — graduated autonomy; high-risk ops can require a named approver
88
+ (`NUTANIX_AUDIT_APPROVED_BY` / `NUTANIX_AUDIT_RATIONALE`).
89
+ - **Undo recording** — reversible writes record an inverse descriptor
90
+ (`vm_update` → prior CPU/memory, `vm_migrate` → prior host).
91
+
92
+ ## Credentials
93
+
94
+ The Prism Central password is stored **encrypted** in
95
+ `~/.nutanix-aiops/secrets.enc` (Fernet + scrypt) — never plaintext on disk.
96
+ Unlock with a master password from `NUTANIX_AIOPS_MASTER_PASSWORD` (MCP/CI) or an
97
+ interactive prompt (CLI). The non-secret connection details (host, port,
98
+ username, verify_ssl) live in `~/.nutanix-aiops/config.yaml`. A legacy plaintext
99
+ env var `NUTANIX_<TARGET>_PASSWORD` is honoured as a fallback.
100
+
101
+ > **Gotcha:** the Prism Central account needs **REST API** rights, not just Web
102
+ > UI access. `doctor`'s REST-RBAC preflight catches this early.
103
+
104
+ ## Supported scope & limitations
105
+
106
+ - **Preview / mock-only.** All behaviour is validated against mocked v4 REST
107
+ responses; it has not been run against a live Prism Central. The fastest live
108
+ check is `nutanix-aiops doctor`.
109
+ - **Self-testable free** on **Nutanix Community Edition (CE)**: a single-node CE
110
+ cluster + an X-Small Prism Central VM.
111
+ - **Least-verified paths:** LCM update (`lcm_update`), protection-domain failover
112
+ (`pd_failover`), and **ESXi-VM listing** in particular need live validation.
113
+ - **Out of scope this release:** IAM / users / roles, Files / Objects / Volumes
114
+ services, reports, X-Play playbooks, and anything outside Prism Central v4.
115
+
116
+ ## Missing a capability?
117
+
118
+ Missing a tool, an API dialect, or a workflow? **Open an issue or PR** —
119
+ feedback and contributions are welcome.
120
+ </content>
@@ -0,0 +1,58 @@
1
+ # Nutanix AIops v0.1.0 — preview
2
+
3
+ Governed AI-ops for **Nutanix Prism Central** (v4 REST API) for AI agents, with a
4
+ built-in governance harness (audit, policy, token/runaway budget, undo-token
5
+ recording, graduated risk tiers) and an encrypted credential store. Standalone —
6
+ no external skill-family dependency.
7
+
8
+ > **Preview / mock-only.** All behaviour is validated against mocked v4 REST
9
+ > responses; it has not been run against a live Prism Central. The fastest live
10
+ > check is `nutanix-aiops doctor`.
11
+
12
+ ## Highlights
13
+
14
+ - **47 MCP tools** (21 read, 26 write), every one wrapped with `@governed_tool`,
15
+ across nine groups:
16
+ - **Clusters** (read) — `cluster_list`, `cluster_health`, `host_list`,
17
+ `cluster_utilization`.
18
+ - **VMs** — `vm_list` (AHV + ESXi), `vm_get` (surfaces ETag); writes
19
+ `vm_power_on` / `vm_guest_shutdown` / `vm_power_off` / `vm_reboot` /
20
+ `vm_create` / `vm_update` (undo prior CPU/mem) / `vm_clone` / `vm_delete`
21
+ (HIGH, dry-run) / `vm_migrate` (HIGH, dry-run, undo → prior host).
22
+ - **Storage** — container list / create / update (undo prior) / delete (HIGH).
23
+ - **Network** — subnet list / get (ETag) / create / delete (HIGH).
24
+ - **Catalog** — image list / delete (HIGH); category list / create / assign
25
+ (bulk).
26
+ - **Data protection / DR** — snapshot list / create / delete (HIGH) / restore
27
+ (HIGH), `recovery_point_list`, `protection_domain_list`, `vm_protect`,
28
+ `pd_failover` (HIGH).
29
+ - **Alerts** — `alert_list`, `event_list`, `audit_list`, **`analyze_alert`**
30
+ (the flagship RCA read), `alert_acknowledge`, `alert_resolve`.
31
+ - **LCM** — `lcm_inventory`, `lcm_precheck`, `lcm_update` (HIGH firmware/software).
32
+ - **Capacity** — `task_list`, `capacity_runway` (days-to-full forecast).
33
+ - **Automatic ETag / If-Match** on every mutation (the v4 footgun) and
34
+ **automatic pagination** on every list; `vm_list` returns **AHV + ESXi**.
35
+ - **Encrypted password store** (`~/.nutanix-aiops/secrets.enc`, Fernet + scrypt)
36
+ — never plaintext on disk; legacy `NUTANIX_<TARGET>_PASSWORD` env fallback.
37
+ - **CLI** with an `init` onboarding wizard, `secret` management, `overview`,
38
+ `cluster` / `vm` sub-commands, and a `doctor` with a REST-RBAC preflight.
39
+ - **Basic-auth REST connection layer** over Prism Central `:9440` with teaching
40
+ error translation.
41
+
42
+ ## Install
43
+
44
+ ```bash
45
+ uv tool install nutanix-aiops
46
+ nutanix-aiops init
47
+ nutanix-aiops doctor
48
+ ```
49
+
50
+ ## Caveats
51
+
52
+ - The Prism Central account needs **REST API** rights, not just Web UI access.
53
+ - Self-testable free on **Nutanix Community Edition (CE)** + X-Small Prism
54
+ Central. The **LCM update**, **PD failover**, and **ESXi-VM listing** paths in
55
+ particular need live verification.
56
+ - Out of scope this release: IAM / users / roles, Files / Objects / Volumes
57
+ services, reports, X-Play playbooks, and anything outside Prism Central v4.
58
+ </content>
@@ -0,0 +1,81 @@
1
+ # Security Policy
2
+
3
+ ## Disclaimer
4
+
5
+ Community-maintained open-source project. **Not affiliated with, endorsed by, or
6
+ sponsored by Nutanix, Inc.** Product and trademark names (Nutanix, Prism, AHV)
7
+ 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/Nutanix-AIops](https://github.com/AIops-tools/Nutanix-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 Prism Central passwords live **encrypted** in
20
+ `~/.nutanix-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 `NUTANIX_<TARGET_NAME_UPPER>_PASSWORD` is still
24
+ honoured as a fallback with a deprecation warning (migrate with
25
+ `nutanix-aiops secret migrate`).
26
+ - The password is used for HTTP Basic auth at request time and held only in
27
+ memory. It is never logged or echoed; the config file holds only host, port,
28
+ username, and TLS settings. Note: the Prism Central account needs REST API
29
+ rights, not just WebUI access.
30
+
31
+ ### Governed Operations
32
+ Every MCP tool runs through the bundled `@governed_tool` harness
33
+ (`nutanix_aiops.governance`):
34
+ - **Audit** — every call logged to a local SQLite DB under `~/.nutanix-aiops/`
35
+ (relocatable via `NUTANIX_AIOPS_HOME`), agent-attributed, secret-redacted.
36
+ - **Token/runaway budget** — hard ceilings (`NUTANIX_MAX_TOOL_CALLS` /
37
+ `NUTANIX_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** — `~/.nutanix-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 entity's BEFORE state
43
+ and record an inverse descriptor (e.g. `vm_power_on`→re-power to prior state,
44
+ `vm_update`→restore prior CPU/memory, `vm_migrate`→migrate back to the prior
45
+ host) so the change can be rolled back.
46
+ - **Automatic ETag / If-Match** — every mutation first fetches the entity's
47
+ current ETag and sends it back as `If-Match`, preventing lost-update (mid-air
48
+ collision) races the v4 API would otherwise reject.
49
+
50
+ ### State-Changing Operations
51
+ Destructive writes — `vm_delete`, `vm_migrate`, `storage_container_delete`,
52
+ `subnet_delete`, `image_delete`, `snapshot_delete`, `snapshot_restore`,
53
+ `pd_failover`, `lcm_update` — are `risk_level=high`, accept a `dry_run` preview,
54
+ and (under `risk_tiers`) require a recorded approver (`NUTANIX_AUDIT_APPROVED_BY`
55
+ + `NUTANIX_AUDIT_RATIONALE`). The CLI additionally double-confirms `vm delete`
56
+ and `vm migrate` and supports `--dry-run`. Reversible medium/low writes capture
57
+ before-state and, where a safe inverse exists, record an undo token.
58
+
59
+ ### SSL/TLS Verification
60
+ `verify_ssl` defaults to true; disable only for self-signed lab certificates.
61
+
62
+ ### Prompt-Injection Protection
63
+ All server-returned text (VM/cluster names, alert titles, extIds, event fields)
64
+ is passed through a `sanitize()` truncate + control-character strip before
65
+ reaching the agent.
66
+
67
+ ### Network Scope
68
+ No webhooks, no telemetry, no outbound calls beyond the configured Prism Central
69
+ REST API endpoint (HTTPS :9440). No post-install scripts or background services.
70
+
71
+ ## Static Analysis
72
+
73
+ ```bash
74
+ uvx bandit -r nutanix_aiops/ mcp_server/
75
+ uv run ruff check .
76
+ ```
77
+
78
+ ## Supported Versions
79
+
80
+ The latest released version receives security fixes. This is a preview (0.x);
81
+ pin a version in production.
@@ -0,0 +1 @@
1
+ """MCP server package for nutanix-aiops."""
@@ -0,0 +1,100 @@
1
+ """Shared MCP server primitives: the FastMCP instance, connection helper,
2
+ error sanitisation, and the ``@tool_errors`` decorator.
3
+
4
+ Tool modules under ``mcp_server/tools/`` import ``mcp`` from here and register
5
+ their ``@mcp.tool()`` functions onto it. ``mcp_server/server.py`` then imports
6
+ those modules and runs the server.
7
+
8
+ Keep ``Optional[X]`` (never PEP 604 ``X | None``) in any FastMCP-reflected
9
+ tool signature — on older mcp/pydantic the union eval'd to ``types.UnionType``
10
+ crashes FastMCP's ``issubclass`` check.
11
+ """
12
+
13
+ import functools
14
+ import logging
15
+ import os
16
+ from collections.abc import Callable
17
+ from pathlib import Path
18
+ from typing import Any, Optional
19
+
20
+ from mcp.server.fastmcp import FastMCP
21
+
22
+ from nutanix_aiops.config import load_config
23
+ from nutanix_aiops.connection import ConnectionManager, NutanixApiError
24
+ from nutanix_aiops.governance import sanitize
25
+
26
+ logger = logging.getLogger(__name__)
27
+
28
+ _DOCTOR_HINT = "Run 'nutanix-aiops doctor' to verify connectivity and credentials."
29
+
30
+
31
+ def _safe_error(exc: Exception, tool: str) -> str:
32
+ """Return an agent-safe error string; log full detail server-side only."""
33
+ logger.error("Tool %s failed", tool, exc_info=True)
34
+ _passthrough = (
35
+ ValueError,
36
+ FileNotFoundError,
37
+ KeyError,
38
+ PermissionError,
39
+ TimeoutError,
40
+ ConnectionError,
41
+ NutanixApiError,
42
+ )
43
+ if isinstance(exc, _passthrough):
44
+ return sanitize(str(exc), 300)
45
+ return f"{type(exc).__name__}: operation failed."
46
+
47
+
48
+ def tool_errors(shape: str = "dict") -> Callable:
49
+ """Wrap a tool body in the canonical try/except → ``_safe_error`` pattern.
50
+
51
+ Place this *between* ``@governed_tool`` and the function so the audit
52
+ decorator and FastMCP still see the original signature.
53
+ """
54
+
55
+ def decorator(func: Callable) -> Callable:
56
+ name = func.__name__
57
+
58
+ @functools.wraps(func)
59
+ def wrapper(*args: Any, **kwargs: Any) -> Any:
60
+ try:
61
+ return func(*args, **kwargs)
62
+ except Exception as e: # noqa: BLE001 — sanitised below
63
+ msg = _safe_error(e, name)
64
+ if shape == "list":
65
+ return [{"error": msg, "hint": _DOCTOR_HINT}]
66
+ if shape == "str":
67
+ return f"Error: {msg} {_DOCTOR_HINT}"
68
+ return {"error": msg, "hint": _DOCTOR_HINT}
69
+
70
+ return wrapper
71
+
72
+ return decorator
73
+
74
+
75
+ mcp = FastMCP(
76
+ "nutanix-aiops",
77
+ instructions=(
78
+ "Nutanix Prism Central (v4) operations (preview): clusters/hosts and "
79
+ "utilization; VM inventory (AHV + ESXi) and lifecycle (power / create / "
80
+ "update / clone / migrate / delete); storage containers; subnets; images "
81
+ "and categories; snapshots / recovery points and protection domains; "
82
+ "alerts / events (list, acknowledge, resolve, analyze); and LCM upgrades. "
83
+ "Mutations auto-handle the v4 ETag/If-Match footgun and auto-paginate. "
84
+ "Destructive writes (delete / migrate / pool changes) are risk=high with a "
85
+ "dry_run preview and require an approver. Every tool runs through the "
86
+ "nutanix-aiops governance harness (audit / budget / risk-tier / undo)."
87
+ ),
88
+ )
89
+
90
+ _conn_mgr: Optional[ConnectionManager] = None
91
+
92
+
93
+ def _get_connection(target: Optional[str] = None) -> Any:
94
+ """Return a Nutanix connection, lazily initialising the manager."""
95
+ global _conn_mgr # noqa: PLW0603
96
+ if _conn_mgr is None:
97
+ config_path_str = os.environ.get("NUTANIX_AIOPS_CONFIG")
98
+ config_path = Path(config_path_str) if config_path_str else None
99
+ _conn_mgr = ConnectionManager(load_config(config_path))
100
+ return _conn_mgr.connect(target)
@@ -0,0 +1,39 @@
1
+ """MCP server wrapping nutanix-aiops operations (stdio transport).
2
+
3
+ Thin adapter layer: each ``@mcp.tool()`` function (in ``mcp_server/tools/``)
4
+ delegates to the ``nutanix_aiops`` ops package and is wrapped with the
5
+ nutanix-aiops ``@governed_tool`` harness (audit / budget / undo / risk-tier).
6
+
7
+ Standalone, self-governed Nutanix Prism Central (v4) operations (preview).
8
+ Cluster / VM / storage / network / snapshot-DR / alert / LCM management with
9
+ automatic ETag & pagination handling.
10
+
11
+ Source: https://github.com/AIops-tools/Nutanix-AIops
12
+ License: MIT
13
+ """
14
+
15
+ import logging
16
+
17
+ from mcp_server._shared import _safe_error, mcp, tool_errors
18
+
19
+ # Importing the tool modules registers every @mcp.tool() onto the shared
20
+ # `mcp` instance. Order does not matter; each module is self-contained.
21
+ from mcp_server.tools import ( # noqa: F401 — side effects
22
+ alerts,
23
+ capacity,
24
+ catalog,
25
+ clusters,
26
+ dataprotection,
27
+ lcm,
28
+ network,
29
+ storage,
30
+ vms,
31
+ )
32
+
33
+ __all__ = ["mcp", "main", "_safe_error", "tool_errors"]
34
+
35
+
36
+ def main() -> None:
37
+ """Run the MCP server over stdio."""
38
+ logging.basicConfig(level=logging.INFO)
39
+ mcp.run(transport="stdio")
@@ -0,0 +1 @@
1
+ """MCP tool modules. Importing each registers its @mcp.tool() functions."""