vmware-storage 2.5.0__tar.gz → 2.6.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.
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/.claude-plugin/plugin.json +1 -1
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/.mcp.json +1 -1
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/PKG-INFO +10 -3
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/README-CN.md +5 -1
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/README.md +8 -1
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/RELEASE_NOTES.md +10 -1
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/SECURITY.md +2 -2
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/openclaw.plugin.json +1 -1
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/package.json +1 -1
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/pyproject.toml +2 -2
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/server.json +2 -2
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/skills/vmware-storage/SKILL.md +2 -2
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/skills/vmware-storage/references/cli-reference.md +13 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/skills/vmware-storage/references/setup-guide.md +3 -3
- vmware_storage-2.6.0/tests/eval/regression/test_datastore_cli_json.py +62 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/uv.lock +3 -3
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/vmware_storage/__init__.py +1 -1
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/vmware_storage/cli.py +12 -6
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/.clawhubignore +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/.env.example +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/.gitignore +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/Dockerfile +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/LICENSE +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/config.example.yaml +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/docker-compose.yml +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/examples/mcp-configs/README.md +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/examples/mcp-configs/claude-code.json +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/examples/mcp-configs/continue.yaml +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/examples/mcp-configs/cursor.json +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/examples/mcp-configs/goose.json +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/examples/mcp-configs/localcowork.json +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/examples/mcp-configs/mcp-agent.yaml +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/examples/mcp-configs/vscode-copilot.json +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/patterns/README.md +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/patterns/iscsi-target-stale-rescan.yaml +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/skills/vmware-storage/evals/evals.json +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/skills/vmware-storage/references/agent-guardrails.md +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/skills/vmware-storage/references/capabilities.md +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/smithery.yaml +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/__init__.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/conftest.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/__init__.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/capability/__init__.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/capability/_family.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/capability/_scores.json +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/capability/_scoring.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/capability/_skill.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/capability/conftest.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/capability/test_entity_reachability.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/capability/test_error_actionability.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/capability/test_tool_description_quality.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/capability/test_tool_manifest_budget.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/__init__.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_atexit_handlers_do_not_accumulate.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_audit_isolation.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_browse_ds_path_join.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_browse_sees_every_file.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_cached_loader_agrees_with_the_resolver.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_capability_grader.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_cli_writes_guarded.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_credential_env_override.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_datastore_list_renders.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_doctor_authenticates_every_target.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_doctor_uses_the_config_the_tools_use.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_env_secret_obfuscation.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_error_hints_fit_the_surface.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_fc_multipath.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_image_registry_cross_process.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_instructions_name_targets.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_inventory_scale_n1.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_iscsi_unreachable_host.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_list_cached_images_target.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_login_without_a_role.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_release_blockers.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_remedy_survives_a_long_home.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_result_envelope.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_returned_failure_is_audited.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_scan_populates_image_cache.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_session_probe_eviction.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_storage_hardening_fixes.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_storage_ops_behavior.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_tool_names_2_0.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_vim_attribute_conformance.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_vsan_efficiency.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_vsan_health_is_actually_queried.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_vsan_reports_what_it_could_not_read.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/spec/__init__.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/spec/vsan_efficiency_endpoints.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/spec/vsan_health_endpoints.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/test_access_info.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/test_datastore_vm_usage.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/test_filelock.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/test_init_and_onboarding.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/test_iscsi_gate.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/test_no_destructive_ops.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/test_no_destructive_vm_code.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/test_policy_roles.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/test_request_error_hints.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/test_safe_error_passthrough.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/test_session_pool.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/test_stop_signal_runs_atexit.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/vmware_storage/_filelock.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/vmware_storage/access_requirements.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/vmware_storage/config.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/vmware_storage/connection.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/vmware_storage/doctor.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/vmware_storage/init_wizard.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/vmware_storage/mcp_server/__init__.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/vmware_storage/mcp_server/__main__.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/vmware_storage/mcp_server/server.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/vmware_storage/notify/__init__.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/vmware_storage/notify/audit.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/vmware_storage/ops/__init__.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/vmware_storage/ops/datastore_browser.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/vmware_storage/ops/datastore_usage.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/vmware_storage/ops/inventory.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/vmware_storage/ops/iscsi_config.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/vmware_storage/ops/iscsi_gate.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/vmware_storage/ops/multipath.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/vmware_storage/ops/storage_paths.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/vmware_storage/ops/vsan.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/vmware_storage/ops/vsan_efficiency.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/vmware_storage/ops/vsan_sdk.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/vmware_storage/policy_environment.py +0 -0
- {vmware_storage-2.5.0 → vmware_storage-2.6.0}/vmware_storage/policy_roles.py +0 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://anthropic.com/claude-code/plugin.schema.json",
|
|
3
3
|
"name": "vmware-storage",
|
|
4
4
|
"displayName": "VMware Storage",
|
|
5
|
-
"version": "2.
|
|
5
|
+
"version": "2.6.0",
|
|
6
6
|
"description": "VMware vSphere storage with 16 MCP tools: datastores, iSCSI, vSAN, FC multipath.",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "Wei Zhou",
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: vmware-storage
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.6.0
|
|
4
4
|
Summary: VMware vSphere storage management: datastores, iSCSI, vSAN. Domain-focused MCP skill.
|
|
5
5
|
Project-URL: Homepage, https://github.com/vmware-skills/VMware-Storage
|
|
6
6
|
Project-URL: Repository, https://github.com/vmware-skills/VMware-Storage
|
|
7
7
|
Project-URL: Issues, https://github.com/vmware-skills/VMware-Storage/issues
|
|
8
8
|
Project-URL: Changelog, https://github.com/vmware-skills/VMware-Storage/blob/main/RELEASE_NOTES.md
|
|
9
|
-
Author-email: Wei Zhou <
|
|
9
|
+
Author-email: Wei Zhou <zhouwei008@gmail.com>
|
|
10
10
|
License-Expression: MIT
|
|
11
11
|
License-File: LICENSE
|
|
12
12
|
Requires-Python: >=3.10
|
|
@@ -24,7 +24,7 @@ Description-Content-Type: text/markdown
|
|
|
24
24
|
|
|
25
25
|
For a read-only check of this skill with your model and agent host, use the shared [model-fit self-test](https://github.com/vmware-skills/marketplace/blob/main/MODEL_FIT_SELF_TEST.md) in the marketplace root.
|
|
26
26
|
|
|
27
|
-
> **Author**: Wei Zhou, VMware by Broadcom —
|
|
27
|
+
> **Author**: Wei Zhou, VMware by Broadcom — zhouwei008@gmail.com
|
|
28
28
|
> This is a community-driven project by a VMware engineer, not an official VMware product.
|
|
29
29
|
> For official VMware developer tools see [developer.broadcom.com](https://developer.broadcom.com).
|
|
30
30
|
|
|
@@ -137,6 +137,13 @@ The `add-target` command automatically rescans storage. Use `--dry-run` to previ
|
|
|
137
137
|
|
|
138
138
|
### Find Deployable Images Across Datastores
|
|
139
139
|
|
|
140
|
+
For scripts, add `--json` to `datastore list`, `datastore browse`, or
|
|
141
|
+
`datastore scan-images`. Successful output is the complete result envelope,
|
|
142
|
+
including `items`, counts, truncation and any cache note. Without the flag,
|
|
143
|
+
list keeps its table and browse/scan-images keep their legacy JSON arrays.
|
|
144
|
+
Other read commands already output JSON by default. Failures still exit nonzero
|
|
145
|
+
with the existing CLI error message.
|
|
146
|
+
|
|
140
147
|
1. List all datastores: `vmware-storage datastore list`
|
|
141
148
|
2. Scan for images: `vmware-storage datastore scan-images datastore01`
|
|
142
149
|
3. Browse with a pattern: `vmware-storage datastore browse datastore01 --pattern "*.iso"`
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
要用自己的模型和 Agent 平台进行只读自测,请看 marketplace 根目录的[共享模型适配自测任务](https://github.com/vmware-skills/marketplace/blob/main/MODEL_FIT_SELF_TEST.md)。
|
|
5
5
|
|
|
6
|
-
> **作者**: Wei Zhou, VMware by Broadcom —
|
|
6
|
+
> **作者**: Wei Zhou, VMware by Broadcom — zhouwei008@gmail.com
|
|
7
7
|
> 本项目由 VMware 工程师维护的社区项目,非 VMware 官方产品。
|
|
8
8
|
> VMware 官方开发者工具请访问 [developer.broadcom.com](https://developer.broadcom.com)。
|
|
9
9
|
|
|
@@ -152,6 +152,10 @@ targets:
|
|
|
152
152
|
|
|
153
153
|
### 查找可部署镜像
|
|
154
154
|
|
|
155
|
+
脚本可为 `datastore list`、`datastore browse`、`datastore scan-images` 添加 `--json`。
|
|
156
|
+
成功时输出完整结果封装,保留 `items`、数量、截断状态及缓存提示。省略该选项时,list 仍为表格,
|
|
157
|
+
browse/scan-images 仍为原有 JSON 数组。其他只读命令已默认输出 JSON;失败仍以非零退出码和现有 CLI 错误消息报告。
|
|
158
|
+
|
|
155
159
|
1. 列出所有数据存储:`vmware-storage datastore list`
|
|
156
160
|
2. 扫描镜像:`vmware-storage datastore scan-images datastore01`
|
|
157
161
|
3. 按模式浏览:`vmware-storage datastore browse datastore01 --pattern "*.iso"`
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
For a read-only check of this skill with your model and agent host, use the shared [model-fit self-test](https://github.com/vmware-skills/marketplace/blob/main/MODEL_FIT_SELF_TEST.md) in the marketplace root.
|
|
5
5
|
|
|
6
|
-
> **Author**: Wei Zhou, VMware by Broadcom —
|
|
6
|
+
> **Author**: Wei Zhou, VMware by Broadcom — zhouwei008@gmail.com
|
|
7
7
|
> This is a community-driven project by a VMware engineer, not an official VMware product.
|
|
8
8
|
> For official VMware developer tools see [developer.broadcom.com](https://developer.broadcom.com).
|
|
9
9
|
|
|
@@ -116,6 +116,13 @@ The `add-target` command automatically rescans storage. Use `--dry-run` to previ
|
|
|
116
116
|
|
|
117
117
|
### Find Deployable Images Across Datastores
|
|
118
118
|
|
|
119
|
+
For scripts, add `--json` to `datastore list`, `datastore browse`, or
|
|
120
|
+
`datastore scan-images`. Successful output is the complete result envelope,
|
|
121
|
+
including `items`, counts, truncation and any cache note. Without the flag,
|
|
122
|
+
list keeps its table and browse/scan-images keep their legacy JSON arrays.
|
|
123
|
+
Other read commands already output JSON by default. Failures still exit nonzero
|
|
124
|
+
with the existing CLI error message.
|
|
125
|
+
|
|
119
126
|
1. List all datastores: `vmware-storage datastore list`
|
|
120
127
|
2. Scan for images: `vmware-storage datastore scan-images datastore01`
|
|
121
128
|
3. Browse with a pattern: `vmware-storage datastore browse datastore01 --pattern "*.iso"`
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
## v2.6.0 — complete datastore CLI JSON envelopes (2026-11-08)
|
|
2
|
+
|
|
3
|
+
* Update public author/project contact metadata to `zhouwei008@gmail.com`.
|
|
4
|
+
|
|
5
|
+
### datastore CLI JSON envelopes
|
|
6
|
+
- Add `--json` to datastore list/browse/scan-images to preserve the complete
|
|
7
|
+
result envelope, including unknown totals, truncation and cache notes.
|
|
8
|
+
- Preserve the existing default table/JSON-array formats and error behavior.
|
|
9
|
+
|
|
1
10
|
## v2.5.0 — per-VM datastore usage and clearer storage refusals (2026-11-01)
|
|
2
11
|
|
|
3
12
|
* New read-only `get_datastore_vm_usage(datastore_name, top_n=10)` reports per-VM committed, uncommitted and unshared space on one datastore, plus attributed/unattributed used space and VMs whose usage could not be measured. It uses one PropertyCollector pass, sorts largest committed usage first, and does not turn unknown into zero. The MCP surface now has 16 tools. Verified against a lab vCenter before this release branch.
|
|
@@ -1388,7 +1397,7 @@ This release tracks vmware-pilot v1.5.17 (new `investigate_alert` template + `re
|
|
|
1388
1397
|
- **[READ]/[WRITE] tool prefixes**: All MCP tool descriptions now start with [READ] or [WRITE] to clearly indicate operation type
|
|
1389
1398
|
- **Read/write split counts**: SKILL.md MCP Tools section header shows exact read vs write tool counts
|
|
1390
1399
|
- **Negative routing**: Description frontmatter includes "Do NOT use when..." clause to prevent misrouting
|
|
1391
|
-
- **Broadcom author attestation**: README.md, README-CN.md, and pyproject.toml include VMware by Broadcom author identity (
|
|
1400
|
+
- **Broadcom author attestation**: README.md, README-CN.md, and pyproject.toml include VMware by Broadcom author identity (zhouwei008@gmail.com) to resolve Snyk E005 brand warnings
|
|
1392
1401
|
|
|
1393
1402
|
### Storage-specific
|
|
1394
1403
|
|
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
|
|
5
5
|
This is a community-maintained open-source project and is **not affiliated with, endorsed by, or sponsored by VMware, Inc. or Broadcom Inc.** "VMware" and "vSphere" are trademarks of Broadcom Inc.
|
|
6
6
|
|
|
7
|
-
**Author**: Wei Zhou, VMware by Broadcom —
|
|
7
|
+
**Author**: Wei Zhou, VMware by Broadcom — zhouwei008@gmail.com
|
|
8
8
|
|
|
9
9
|
## Reporting Vulnerabilities
|
|
10
10
|
|
|
11
11
|
If you discover a security vulnerability, please report it privately:
|
|
12
12
|
|
|
13
|
-
- **Email**:
|
|
13
|
+
- **Email**: zhouwei008@gmail.com
|
|
14
14
|
- **GitHub**: Open a [private security advisory](https://github.com/vmware-skills/VMware-Storage/security/advisories/new)
|
|
15
15
|
|
|
16
16
|
Do **not** open a public GitHub issue for security vulnerabilities.
|
|
@@ -4,12 +4,12 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "vmware-storage"
|
|
7
|
-
version = "2.
|
|
7
|
+
version = "2.6.0"
|
|
8
8
|
description = "VMware vSphere storage management: datastores, iSCSI, vSAN. Domain-focused MCP skill."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
11
11
|
requires-python = ">=3.10"
|
|
12
|
-
authors = [{ name = "Wei Zhou", email = "
|
|
12
|
+
authors = [{ name = "Wei Zhou", email = "zhouwei008@gmail.com" }]
|
|
13
13
|
dependencies = [
|
|
14
14
|
"pyvmomi>=8.0.3.0,<10.0",
|
|
15
15
|
"pyaml>=24.0,<27.0",
|
|
@@ -7,12 +7,12 @@
|
|
|
7
7
|
"url": "https://github.com/vmware-skills/VMware-Storage",
|
|
8
8
|
"source": "github"
|
|
9
9
|
},
|
|
10
|
-
"version": "2.
|
|
10
|
+
"version": "2.6.0",
|
|
11
11
|
"packages": [
|
|
12
12
|
{
|
|
13
13
|
"registryType": "pypi",
|
|
14
14
|
"identifier": "vmware-storage",
|
|
15
|
-
"version": "2.
|
|
15
|
+
"version": "2.6.0",
|
|
16
16
|
"runtimeHint": "uvx",
|
|
17
17
|
"packageArguments": [
|
|
18
18
|
{
|
|
@@ -42,7 +42,7 @@ VMware vSphere storage management — 16 MCP tools for datastores, iSCSI, vSAN,
|
|
|
42
42
|
## Quick Install
|
|
43
43
|
|
|
44
44
|
```bash
|
|
45
|
-
uv tool install vmware-storage==2.
|
|
45
|
+
uv tool install vmware-storage==2.6.0
|
|
46
46
|
vmware-storage init # guided setup: writes config + .env (chmod 600, password grep-safe), then verifies
|
|
47
47
|
vmware-storage doctor
|
|
48
48
|
```
|
|
@@ -274,7 +274,7 @@ Corporate TLS proxies inject certificates that uv's bundled CA store doesn't tru
|
|
|
274
274
|
## Setup
|
|
275
275
|
|
|
276
276
|
```bash
|
|
277
|
-
uv tool install vmware-storage==2.
|
|
277
|
+
uv tool install vmware-storage==2.6.0
|
|
278
278
|
mkdir -p ~/.vmware-storage
|
|
279
279
|
cp config.example.yaml ~/.vmware-storage/config.yaml
|
|
280
280
|
# Edit config.yaml with your vCenter/ESXi targets
|
{vmware_storage-2.5.0 → vmware_storage-2.6.0}/skills/vmware-storage/references/cli-reference.md
RENAMED
|
@@ -276,3 +276,16 @@ Privileges are checked on the root folder: `not_granted_at_root` may still be gr
|
|
|
276
276
|
|----------|-------------|
|
|
277
277
|
| `VMWARE_STORAGE_CONFIG` | Override config file path (used by MCP server) |
|
|
278
278
|
| `VMWARE_<TARGET>_PASSWORD` | Password for a target (e.g., `VMWARE_MY_VCENTER_PASSWORD`) |
|
|
279
|
+
|
|
280
|
+
### Datastore JSON envelopes
|
|
281
|
+
|
|
282
|
+
Add `--json` to `datastore list`, `datastore browse`, or `datastore scan-images`
|
|
283
|
+
for the full successful result envelope, matching the MCP operation's result:
|
|
284
|
+
`items`, `returned`, `limit`, `total`, `truncated`, `hint`, and any extra evidence
|
|
285
|
+
such as `cache_note`. Unknown/null values remain unknown, not zero or complete.
|
|
286
|
+
A successful image scan can carry a local-cache failure note; do not discard it.
|
|
287
|
+
|
|
288
|
+
Without this option list prints its table and browse/scan-images retain their
|
|
289
|
+
legacy JSON arrays. Other read commands already emit JSON by default. This flag
|
|
290
|
+
does not alter reads, local-cache writes, Policy or auditing. Errors retain the
|
|
291
|
+
existing text message and nonzero exit code; scripts must check the exit status.
|
{vmware_storage-2.5.0 → vmware_storage-2.6.0}/skills/vmware-storage/references/setup-guide.md
RENAMED
|
@@ -13,19 +13,19 @@ Complete setup and security guide for `vmware-storage`.
|
|
|
13
13
|
### Via uv (recommended)
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
|
-
uv tool install vmware-storage==2.
|
|
16
|
+
uv tool install vmware-storage==2.6.0
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
### Via pip
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
|
-
pip install vmware-storage==2.
|
|
22
|
+
pip install vmware-storage==2.6.0
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
### From source
|
|
26
26
|
|
|
27
27
|
```bash
|
|
28
|
-
git clone --branch v2.
|
|
28
|
+
git clone --branch v2.6.0 https://github.com/vmware-skills/VMware-Storage.git
|
|
29
29
|
cd VMware-Storage
|
|
30
30
|
pip install -e .
|
|
31
31
|
```
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"""Successful JSON output must preserve coverage and local-cache evidence."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import json
|
|
5
|
+
from types import SimpleNamespace
|
|
6
|
+
|
|
7
|
+
import pytest
|
|
8
|
+
from typer.testing import CliRunner
|
|
9
|
+
|
|
10
|
+
from vmware_storage import cli
|
|
11
|
+
from vmware_storage.ops import datastore_browser, inventory
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@pytest.fixture
|
|
15
|
+
def connection(monkeypatch):
|
|
16
|
+
si = object()
|
|
17
|
+
monkeypatch.setattr(cli, "_get_connection", lambda *a: si)
|
|
18
|
+
monkeypatch.setattr(cli, "load_config", lambda *a: object())
|
|
19
|
+
monkeypatch.setattr(cli, "ConnectionManager", lambda *a: SimpleNamespace(
|
|
20
|
+
resolve_target_name=lambda target: "lab", connect=lambda target: si))
|
|
21
|
+
return si
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _envelope(items):
|
|
25
|
+
return {"items": items, "returned": len(items), "limit": 2,
|
|
26
|
+
"total": None, "truncated": True, "hint": "incomplete evidence"}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@pytest.mark.parametrize("command,owner,operation", [
|
|
30
|
+
(["list"], inventory, "list_datastores"),
|
|
31
|
+
(["browse", "ds"], datastore_browser, "browse_datastore"),
|
|
32
|
+
(["scan-images", "ds"], datastore_browser, "scan_images"),
|
|
33
|
+
])
|
|
34
|
+
@pytest.mark.parametrize("items", [[], [{"name": "[SSD] 数据", "usage_pct": None}]])
|
|
35
|
+
def test_json_preserves_envelope_even_when_empty_or_unknown(
|
|
36
|
+
monkeypatch, connection, command, owner, operation, items,
|
|
37
|
+
):
|
|
38
|
+
envelope = _envelope(items)
|
|
39
|
+
envelope["cache_note"] = "Scan succeeded but the local cache was not updated"
|
|
40
|
+
calls = []
|
|
41
|
+
|
|
42
|
+
def read(si, *a, **kw):
|
|
43
|
+
assert si is connection
|
|
44
|
+
calls.append(kw)
|
|
45
|
+
return envelope
|
|
46
|
+
|
|
47
|
+
monkeypatch.setattr(owner, operation, read)
|
|
48
|
+
out = CliRunner().invoke(cli.app, ["datastore", *command, "--json"])
|
|
49
|
+
assert out.exit_code == 0, out.output
|
|
50
|
+
assert json.loads(out.stdout) == envelope
|
|
51
|
+
assert len(calls) == 1
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
@pytest.mark.parametrize("command,operation", [
|
|
55
|
+
(["browse", "ds"], "browse_datastore"), (["scan-images", "ds"], "scan_images"),
|
|
56
|
+
])
|
|
57
|
+
def test_legacy_json_arrays_are_unchanged_without_flag(monkeypatch, connection, command, operation):
|
|
58
|
+
items = [{"name": "image.iso"}]
|
|
59
|
+
monkeypatch.setattr(datastore_browser, operation, lambda *a, **kw: _envelope(items))
|
|
60
|
+
out = CliRunner().invoke(cli.app, ["datastore", *command])
|
|
61
|
+
assert out.exit_code == 0, out.output
|
|
62
|
+
assert json.loads(out.stdout) == items
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
version = 1
|
|
2
|
-
revision =
|
|
2
|
+
revision = 5
|
|
3
3
|
requires-python = ">=3.10"
|
|
4
4
|
resolution-markers = [
|
|
5
5
|
"python_full_version >= '3.14' and sys_platform == 'win32'",
|
|
@@ -341,7 +341,7 @@ name = "exceptiongroup"
|
|
|
341
341
|
version = "1.3.1"
|
|
342
342
|
source = { registry = "https://pypi.org/simple" }
|
|
343
343
|
dependencies = [
|
|
344
|
-
{ name = "typing-extensions"
|
|
344
|
+
{ name = "typing-extensions" },
|
|
345
345
|
]
|
|
346
346
|
sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" }
|
|
347
347
|
wheels = [
|
|
@@ -1176,7 +1176,7 @@ wheels = [
|
|
|
1176
1176
|
|
|
1177
1177
|
[[package]]
|
|
1178
1178
|
name = "vmware-storage"
|
|
1179
|
-
version = "2.
|
|
1179
|
+
version = "2.6.0"
|
|
1180
1180
|
source = { editable = "." }
|
|
1181
1181
|
dependencies = [
|
|
1182
1182
|
{ name = "mcp", extra = ["cli"] },
|
|
@@ -208,6 +208,7 @@ def _usage_cell(usage_pct: float | None) -> Text:
|
|
|
208
208
|
@handle_cli_errors
|
|
209
209
|
@audited("list_all_datastores")
|
|
210
210
|
def ds_list(
|
|
211
|
+
as_json: bool = typer.Option(False, "--json", help="Return the complete result envelope"),
|
|
211
212
|
target: str | None = typer.Option(None, help="Target name"),
|
|
212
213
|
config: str | None = typer.Option(None, "--config", help="Config file path"),
|
|
213
214
|
) -> None:
|
|
@@ -215,8 +216,11 @@ def ds_list(
|
|
|
215
216
|
from vmware_storage.ops.inventory import list_datastores
|
|
216
217
|
|
|
217
218
|
si = _get_connection(target, config)
|
|
218
|
-
result = list_datastores(si, include_vm_count=True)
|
|
219
|
+
result = list_datastores(si, include_vm_count=True)
|
|
219
220
|
_audit.log_query(target=target or "default", resource="datastores", query_type="list")
|
|
221
|
+
if as_json:
|
|
222
|
+
_print_json(result)
|
|
223
|
+
return
|
|
220
224
|
table = Table(title="Datastores")
|
|
221
225
|
table.add_column("Name", style="bold")
|
|
222
226
|
table.add_column("Type")
|
|
@@ -224,7 +228,7 @@ def ds_list(
|
|
|
224
228
|
table.add_column("Free GB", justify="right")
|
|
225
229
|
table.add_column("Usage %", justify="right")
|
|
226
230
|
table.add_column("VMs", justify="right")
|
|
227
|
-
for ds in result:
|
|
231
|
+
for ds in result["items"]:
|
|
228
232
|
table.add_row(
|
|
229
233
|
# Text(), not str: a datastore may legally be called "[SSD] prod",
|
|
230
234
|
# and vCenter's name is data, not markup we wrote.
|
|
@@ -245,6 +249,7 @@ def ds_browse(
|
|
|
245
249
|
ds_name: str = typer.Argument(help="Datastore name"),
|
|
246
250
|
path: str = typer.Option("", help="Subdirectory path"),
|
|
247
251
|
pattern: str = typer.Option("*", help="Glob pattern"),
|
|
252
|
+
as_json: bool = typer.Option(False, "--json", help="Return the complete result envelope"),
|
|
248
253
|
target: str | None = typer.Option(None, help="Target name"),
|
|
249
254
|
config: str | None = typer.Option(None, "--config", help="Config file path"),
|
|
250
255
|
) -> None:
|
|
@@ -252,9 +257,9 @@ def ds_browse(
|
|
|
252
257
|
from vmware_storage.ops.datastore_browser import browse_datastore
|
|
253
258
|
|
|
254
259
|
si = _get_connection(target, config)
|
|
255
|
-
result = browse_datastore(si, ds_name, path=path, pattern=pattern)
|
|
260
|
+
result = browse_datastore(si, ds_name, path=path, pattern=pattern)
|
|
256
261
|
_audit.log_query(target=target or "default", resource=ds_name, query_type="browse")
|
|
257
|
-
_print_json(result)
|
|
262
|
+
_print_json(result if as_json else result["items"])
|
|
258
263
|
|
|
259
264
|
|
|
260
265
|
@ds_app.command("scan-images")
|
|
@@ -262,6 +267,7 @@ def ds_browse(
|
|
|
262
267
|
@audited("scan_datastore_images")
|
|
263
268
|
def ds_scan_images(
|
|
264
269
|
ds_name: str = typer.Argument(help="Datastore name"),
|
|
270
|
+
as_json: bool = typer.Option(False, "--json", help="Return the complete result envelope"),
|
|
265
271
|
target: str | None = typer.Option(None, help="Target name"),
|
|
266
272
|
config: str | None = typer.Option(None, "--config", help="Config file path"),
|
|
267
273
|
) -> None:
|
|
@@ -271,9 +277,9 @@ def ds_scan_images(
|
|
|
271
277
|
conn_mgr = ConnectionManager(load_config(Path(config) if config else None))
|
|
272
278
|
name = conn_mgr.resolve_target_name(target)
|
|
273
279
|
si = conn_mgr.connect(name)
|
|
274
|
-
result = scan_images(si, ds_name, target=name)
|
|
280
|
+
result = scan_images(si, ds_name, target=name)
|
|
275
281
|
_audit.log_query(target=target or "default", resource=ds_name, query_type="scan_images")
|
|
276
|
-
_print_json(result)
|
|
282
|
+
_print_json(result if as_json else result["items"])
|
|
277
283
|
|
|
278
284
|
|
|
279
285
|
# ---------------------------------------------------------------------------
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{vmware_storage-2.5.0 → vmware_storage-2.6.0}/skills/vmware-storage/references/agent-guardrails.md
RENAMED
|
File without changes
|
{vmware_storage-2.5.0 → vmware_storage-2.6.0}/skills/vmware-storage/references/capabilities.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/capability/test_entity_reachability.py
RENAMED
|
File without changes
|
{vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/capability/test_error_actionability.py
RENAMED
|
File without changes
|
{vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/capability/test_tool_description_quality.py
RENAMED
|
File without changes
|
{vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/capability/test_tool_manifest_budget.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_browse_ds_path_join.py
RENAMED
|
File without changes
|
{vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_browse_sees_every_file.py
RENAMED
|
File without changes
|
|
File without changes
|
{vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_capability_grader.py
RENAMED
|
File without changes
|
{vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_cli_writes_guarded.py
RENAMED
|
File without changes
|
{vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_credential_env_override.py
RENAMED
|
File without changes
|
{vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_datastore_list_renders.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_env_secret_obfuscation.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_inventory_scale_n1.py
RENAMED
|
File without changes
|
{vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_iscsi_unreachable_host.py
RENAMED
|
File without changes
|
|
File without changes
|
{vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_login_without_a_role.py
RENAMED
|
File without changes
|
{vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_release_blockers.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_session_probe_eviction.py
RENAMED
|
File without changes
|
{vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_storage_hardening_fixes.py
RENAMED
|
File without changes
|
{vmware_storage-2.5.0 → vmware_storage-2.6.0}/tests/eval/regression/test_storage_ops_behavior.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|