vmware-aiops 2.3.2__tar.gz → 2.4.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_aiops-2.3.2 → vmware_aiops-2.4.0}/.claude-plugin/plugin.json +1 -1
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/.mcp.json +1 -1
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/PKG-INFO +2 -1
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/README-CN.md +1 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/README.md +1 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/RELEASE_NOTES.md +9 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/openclaw.plugin.json +1 -1
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/package.json +1 -1
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/pyproject.toml +1 -1
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/server.json +2 -2
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/skills/vmware-aiops/SKILL.md +2 -2
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/skills/vmware-aiops/references/setup-guide.md +6 -5
- vmware_aiops-2.4.0/tests/test_policy_roles.py +117 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/uv.lock +5 -5
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/__init__.py +1 -1
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/policy_environment.py +3 -0
- vmware_aiops-2.4.0/vmware_aiops/policy_roles.py +123 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/.clawhubignore +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/.env.example +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/.github/dependabot.yml +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/.gitignore +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/Dockerfile +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/LICENSE +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/SECURITY.md +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/config.example.yaml +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/docker-compose.yml +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/docs/integrations/continue.md +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/docs/integrations/cursor.md +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/docs/integrations/goose.md +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/docs/integrations/localcowork.md +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/docs/integrations/mcp-agent.md +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/docs/integrations/vscode-copilot.md +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/docs/plans/2026-03-09-plan-apply-design.md +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/examples/deploy.yaml +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/examples/mcp-configs/README.md +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/examples/mcp-configs/claude-code.json +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/examples/mcp-configs/continue.yaml +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/examples/mcp-configs/cursor.json +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/examples/mcp-configs/goose.json +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/examples/mcp-configs/localcowork.json +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/examples/mcp-configs/mcp-agent.yaml +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/examples/mcp-configs/vscode-copilot.json +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/examples/ollama-local-setup.md +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/skills/vmware-aiops/evals/evals.json +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/skills/vmware-aiops/references/agent-guardrails.md +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/skills/vmware-aiops/references/capabilities.md +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/skills/vmware-aiops/references/cli-reference.md +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/skills/vmware-aiops/references/investigation-protocol.md +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/smithery.yaml +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/__init__.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/conftest.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/__init__.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/capability/__init__.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/capability/_family.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/capability/_scores.json +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/capability/_scoring.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/capability/_skill.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/capability/conftest.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/capability/test_entity_reachability.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/capability/test_error_actionability.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/capability/test_tool_description_quality.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/capability/test_tool_manifest_budget.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/__init__.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/_diag_fakes.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/_pc_fakes.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/test_aiops_specific.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/test_alarm_health_scale_n1.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/test_atexit_handlers_do_not_accumulate.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/test_capability_grader.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/test_cli_destructive_guards.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/test_cli_writes_guarded.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/test_cluster_health_summary_delegation.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/test_code_review_fixes.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/test_config_path_resolution_is_shared.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/test_daemon_calls_are_audited.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/test_daemon_host_log_cycles.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/test_deploy_correctness.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/test_doctor_authenticates_every_target.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/test_documented_gates_match_the_registry.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/test_enum_params_match_implementation.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/test_env_secret_obfuscation.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/test_event_sets_match_real_class_names.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/test_events_are_read_newest_first.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/test_guest_download_writes_the_local_disk.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/test_guest_username_is_explicit.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/test_host_log_scan_reads_real_logs.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/test_host_paths_protected.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/test_instructions_name_targets.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/test_inventory_scale_issue31.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/test_list_envelope_conformance.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/test_list_plans_is_non_destructive.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/test_login_without_vsphere_role.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/test_mcp_frame_marks_failures.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/test_ova_network_mapping.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/test_release_blockers.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/test_result_envelope.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/test_returned_failure_is_audited.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/test_session_probe_eviction.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/test_set_ttl_safety.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/test_snapshot_async.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/test_text_io_declares_encoding.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/test_tool_annotations_match_behaviour.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/test_unreachable_host_vmks.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/test_v1_5_25_blockers.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/test_vim_attribute_conformance.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/test_access_info.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/test_cluster_mgmt_sanitize.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/test_cluster_ttl_plan_gate.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/test_concurrent_local_state.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/test_config.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/test_drs_rules.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/test_gate_review_fixes.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/test_guest_tools_gate.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/test_host_network_mgmt.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/test_init_and_onboarding.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/test_network_mgmt.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/test_no_destructive_ops.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/test_plan_gate_narrow_fixes.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/test_plan_rollback_final_fixes.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/test_reset_alarm_gate.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/test_results_name_their_target.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/test_safe_error_passthrough.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/test_session_pool.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/test_stop_signal_runs_atexit.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/test_vm_delete_blast_radius.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/test_vm_tools_gate.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/_fsutil.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/access_requirements.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/cli/__init__.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/cli/_common.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/cli/_root.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/cli/access.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/cli/alarm.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/cli/cluster.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/cli/deploy.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/cli/doctor.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/cli/hub.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/cli/investigate.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/cli/mcp_config.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/cli/plan.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/cli/scan.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/cli/summary.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/cli/vm.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/config.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/connection.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/doctor.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/init_wizard.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/mcp_server/__init__.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/mcp_server/__main__.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/mcp_server/_shared.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/mcp_server/server.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/mcp_server/tools/__init__.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/mcp_server/tools/access.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/mcp_server/tools/alarm.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/mcp_server/tools/cluster.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/mcp_server/tools/datastore.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/mcp_server/tools/deploy.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/mcp_server/tools/guest.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/mcp_server/tools/network.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/mcp_server/tools/plan.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/mcp_server/tools/summary.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/mcp_server/tools/ttl.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/mcp_server/tools/vm.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/notify/__init__.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/notify/audit.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/notify/logger.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/notify/webhook.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/ops/__init__.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/ops/_paging.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/ops/alarm_mgmt.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/ops/cluster_gate.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/ops/cluster_mgmt.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/ops/datastore_browser.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/ops/gate.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/ops/guest_gate.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/ops/guest_ops.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/ops/health.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/ops/host_network_mgmt.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/ops/inventory.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/ops/iscsi_config.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/ops/network_mgmt.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/ops/ova_deploy.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/ops/plan_executor.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/ops/plan_gate.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/ops/planner.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/ops/ttl.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/ops/vm_delete_gate.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/ops/vm_deploy.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/ops/vm_gate.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/ops/vm_lifecycle.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/scanner/__init__.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/scanner/alarm_scanner.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/scanner/log_scanner.py +0 -0
- {vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/vmware_aiops/scanner/scheduler.py +0 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://anthropic.com/claude-code/plugin.schema.json",
|
|
3
3
|
"name": "vmware-aiops",
|
|
4
4
|
"displayName": "VMware AIops",
|
|
5
|
-
"version": "2.
|
|
5
|
+
"version": "2.4.0",
|
|
6
6
|
"description": "AI-powered VMware vCenter/ESXi VM lifecycle and deployment with 61 MCP tools.",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "Wei Zhou",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: vmware-aiops
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.4.0
|
|
4
4
|
Summary: VMware vCenter/ESXi AI-powered VM lifecycle and deployment tool
|
|
5
5
|
Project-URL: Homepage, https://github.com/vmware-skills/VMware-AIops
|
|
6
6
|
Project-URL: Repository, https://github.com/vmware-skills/VMware-AIops
|
|
@@ -1204,6 +1204,7 @@ claude mcp add --transport http vmware-aiops https://mcp.example.com:8443/mcp \
|
|
|
1204
1204
|
(default 2) sessions per target; each session is a login on the target, and a call waits at most 300 s for one.
|
|
1205
1205
|
- **Everyone who can reach the endpoint acts with this server's account.** Tokens identify callers; they grant
|
|
1206
1206
|
nothing on the platform. Run one endpoint per privilege level.
|
|
1207
|
+
- **Several people or roles on one endpoint:** run `vmware-audit roles enable` once, then give each token a role (`vmware-audit token create NAME --role reader`, or a role in `roles.yaml` naming tools and targets; vmware-policy ≥ 1.24.0). A role limits what the token may call on this endpoint; it cannot grant more than the account has. See vmware-policy's README, "Roles for network callers".
|
|
1207
1208
|
|
|
1208
1209
|
**Offer only read tools, plus the writes you choose:**
|
|
1209
1210
|
|
|
@@ -843,6 +843,7 @@ claude mcp add --transport http vmware-aiops https://mcp.example.com:8443/mcp \
|
|
|
843
843
|
个会话;每个会话都是在该 target 上的一次登录,一个调用最多等待 300 秒拿到会话。
|
|
844
844
|
- **能连到这个端点的人,都以该 server 配置的账号操作。** token 只用来识别调用者,不在平台上授予任何权限。
|
|
845
845
|
每个权限级别单独起一个端点。
|
|
846
|
+
- **一个端点给多人或多种角色用:** 先运行一次 `vmware-audit roles enable`,再给每个 token 指定角色(`vmware-audit token create 名字 --role reader`,或在 `roles.yaml` 里定义可用的工具和 target;需 vmware-policy ≥ 1.24.0)。角色只能限定这个 token 在本端点上能调用什么,不能超出账号本身的权限。详见 vmware-policy README 的「网络调用者的角色」一节。
|
|
846
847
|
|
|
847
848
|
**只提供读工具,加上你选定的写工具:**
|
|
848
849
|
|
|
@@ -1180,6 +1180,7 @@ claude mcp add --transport http vmware-aiops https://mcp.example.com:8443/mcp \
|
|
|
1180
1180
|
(default 2) sessions per target; each session is a login on the target, and a call waits at most 300 s for one.
|
|
1181
1181
|
- **Everyone who can reach the endpoint acts with this server's account.** Tokens identify callers; they grant
|
|
1182
1182
|
nothing on the platform. Run one endpoint per privilege level.
|
|
1183
|
+
- **Several people or roles on one endpoint:** run `vmware-audit roles enable` once, then give each token a role (`vmware-audit token create NAME --role reader`, or a role in `roles.yaml` naming tools and targets; vmware-policy ≥ 1.24.0). A role limits what the token may call on this endpoint; it cannot grant more than the account has. See vmware-policy's README, "Roles for network callers".
|
|
1183
1184
|
|
|
1184
1185
|
**Offer only read tools, plus the writes you choose:**
|
|
1185
1186
|
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
## v2.4.0 — roles for network callers (HLD §18)
|
|
2
|
+
|
|
3
|
+
* Declares the role metadata vmware-policy ≥ 1.24.0 needs to apply **roles** to this server over HTTPS
|
|
4
|
+
(HLD §18): how a missing target resolves, the guest and host-file tools that escape a role, and what each composite tool can run — `apply_vm_plan` and `rollback_vm_plan` reach every tool a plan step maps to plus `delete_vm` (rollback), `set_vm_ttl` reaches `delete_vm`, the batch tools reach the deploy and clone tools and the follow-up steps their arguments ask for (`reconfigure_vm`, `create_vm_snapshot`, `power_on_vm`, and `attach_iso_to_vm` for a deployment spec); a test derives these from what the batch code calls. A role may allow a composite only if it allows all of them. A test fails when a new plan action is not mapped to a tool. With an older vmware-policy nothing changes. Once an operator runs
|
|
5
|
+
`vmware-audit roles enable`, a token's role decides which tools and targets it may use here; a refused call is
|
|
6
|
+
audited as `denied`. See vmware-policy's README, "Roles for network callers".
|
|
7
|
+
* A target-limited role is checked against the same config the connection uses: the copy the server's connection manager loaded on its first connection. Edit `config.yaml` and restart for both to see the change.
|
|
8
|
+
* README and setup guide: one endpoint for several people or roles (run `vmware-audit roles enable` first).
|
|
9
|
+
|
|
1
10
|
## v2.3.2 — tools may not touch this server's own control files
|
|
2
11
|
|
|
3
12
|
* **Security fix (HLD §18 step 0).** guest file download/upload, OVA and deployment-spec paths could name this server's own files, so over HTTPS a token holder could
|
|
@@ -7,12 +7,12 @@
|
|
|
7
7
|
"url": "https://github.com/vmware-skills/VMware-AIops",
|
|
8
8
|
"source": "github"
|
|
9
9
|
},
|
|
10
|
-
"version": "2.
|
|
10
|
+
"version": "2.4.0",
|
|
11
11
|
"packages": [
|
|
12
12
|
{
|
|
13
13
|
"registryType": "pypi",
|
|
14
14
|
"identifier": "vmware-aiops",
|
|
15
|
-
"version": "2.
|
|
15
|
+
"version": "2.4.0",
|
|
16
16
|
"runtimeHint": "uvx",
|
|
17
17
|
"packageArguments": [
|
|
18
18
|
{
|
|
@@ -63,7 +63,7 @@ Read before connecting an agent. Per-tool inventory: `references/capabilities.md
|
|
|
63
63
|
## Quick Install
|
|
64
64
|
|
|
65
65
|
```bash
|
|
66
|
-
uv tool install vmware-aiops==2.
|
|
66
|
+
uv tool install vmware-aiops==2.4.0
|
|
67
67
|
vmware-aiops doctor
|
|
68
68
|
vmware-aiops hub status # see which family members are installed
|
|
69
69
|
```
|
|
@@ -303,7 +303,7 @@ The account has no vSphere role. Assign one (Read-Only or higher) on the vCenter
|
|
|
303
303
|
## Setup
|
|
304
304
|
|
|
305
305
|
```bash
|
|
306
|
-
uv tool install vmware-aiops==2.
|
|
306
|
+
uv tool install vmware-aiops==2.4.0
|
|
307
307
|
mkdir -p ~/.vmware-aiops
|
|
308
308
|
vmware-aiops init # generates config.yaml and .env templates
|
|
309
309
|
chmod 600 ~/.vmware-aiops/.env
|
|
@@ -6,13 +6,13 @@ All install methods fetch from the same source: [github.com/vmware-skills/VMware
|
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
8
|
# Via PyPI (recommended for version pinning)
|
|
9
|
-
uv tool install vmware-aiops==2.
|
|
9
|
+
uv tool install vmware-aiops==2.4.0
|
|
10
10
|
|
|
11
11
|
# Via Skills.sh (fetches from GitHub)
|
|
12
|
-
npx skills add vmware-skills/VMware-AIops#v2.
|
|
12
|
+
npx skills add vmware-skills/VMware-AIops#v2.4.0
|
|
13
13
|
|
|
14
14
|
# Via ClawHub (fetches from ClawHub registry snapshot of GitHub)
|
|
15
|
-
clawhub install @zw008/vmware-aiops --version 2.
|
|
15
|
+
clawhub install @zw008/vmware-aiops --version 2.4.0
|
|
16
16
|
```
|
|
17
17
|
|
|
18
18
|
### Claude Code
|
|
@@ -35,7 +35,7 @@ claude mcp add vmware-aiops -- vmware-aiops mcp
|
|
|
35
35
|
|
|
36
36
|
```bash
|
|
37
37
|
# 1. Install from PyPI (source: github.com/vmware-skills/VMware-AIops)
|
|
38
|
-
uv tool install vmware-aiops==2.
|
|
38
|
+
uv tool install vmware-aiops==2.4.0
|
|
39
39
|
|
|
40
40
|
# 2. Verify installation source
|
|
41
41
|
vmware-aiops --version # confirms installed version
|
|
@@ -73,7 +73,7 @@ The `vmware-aiops` package installs a Python CLI binary and its dependencies (py
|
|
|
73
73
|
## Development Install
|
|
74
74
|
|
|
75
75
|
```bash
|
|
76
|
-
git clone --branch v2.
|
|
76
|
+
git clone --branch v2.4.0 https://github.com/vmware-skills/VMware-AIops.git
|
|
77
77
|
cd VMware-AIops
|
|
78
78
|
uv venv && source .venv/bin/activate
|
|
79
79
|
# --no-sources: pyproject's [tool.uv.sources] points vmware-monitor at a sibling
|
|
@@ -245,4 +245,5 @@ vmware-aiops mcp --transport https --host 0.0.0.0 --port 8443 \
|
|
|
245
245
|
- **Everyone who can reach the endpoint acts with this server's account.** Tokens identify callers; they grant
|
|
246
246
|
nothing on the platform. Run one endpoint per privilege level (for example a read-only account behind
|
|
247
247
|
`--expose read`, and a separate endpoint for operators).
|
|
248
|
+
- **Several people or roles on one endpoint:** run `vmware-audit roles enable` once, then give each token a role (`vmware-audit token create NAME --role reader`, or a role in `roles.yaml` naming tools and targets; vmware-policy ≥ 1.24.0). A role limits what the token may call on this endpoint; it cannot grant more than the account has. See vmware-policy's README, "Roles for network callers".
|
|
248
249
|
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"""HLD §18 D-22: the role metadata this skill declares matches its real code."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import asyncio
|
|
6
|
+
|
|
7
|
+
import pytest
|
|
8
|
+
|
|
9
|
+
from vmware_aiops import policy_roles
|
|
10
|
+
from vmware_aiops.ops.plan_executor import dispatch_actions
|
|
11
|
+
from vmware_aiops.ops.plan_gate import REFUSED_ACTIONS
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _registry() -> set[str]:
|
|
15
|
+
from vmware_aiops.mcp_server.server import mcp
|
|
16
|
+
|
|
17
|
+
return {t.name for t in asyncio.run(mcp.list_tools())}
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@pytest.mark.unit
|
|
21
|
+
def test_every_plan_action_is_mapped_or_refused():
|
|
22
|
+
"""A new plan action must name the tool it amounts to, or a role could reach it unlisted."""
|
|
23
|
+
missing = dispatch_actions() - set(policy_roles.ACTION_TOOLS) - set(REFUSED_ACTIONS)
|
|
24
|
+
assert not missing, f"map these plan actions in policy_roles.ACTION_TOOLS: {sorted(missing)}"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@pytest.mark.unit
|
|
28
|
+
def test_every_declared_name_is_a_real_tool():
|
|
29
|
+
tools = _registry()
|
|
30
|
+
named = set(policy_roles.ESCAPES) | set(policy_roles.REACHES)
|
|
31
|
+
for reached in policy_roles.REACHES.values():
|
|
32
|
+
named |= reached
|
|
33
|
+
named |= set(policy_roles.ACTION_TOOLS.values())
|
|
34
|
+
assert named - tools == set(), sorted(named - tools)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@pytest.mark.unit
|
|
38
|
+
def test_plans_reach_delete_through_rollback():
|
|
39
|
+
assert "delete_vm" in policy_roles.REACHES["apply_vm_plan"]
|
|
40
|
+
assert "delete_vm" in policy_roles.REACHES["set_vm_ttl"]
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@pytest.mark.unit
|
|
44
|
+
def test_metadata_is_declared_when_policy_has_roles():
|
|
45
|
+
roles = pytest.importorskip("vmware_policy.roles")
|
|
46
|
+
meta = roles.metadata("aiops")
|
|
47
|
+
assert meta is not None and meta.version == 1
|
|
48
|
+
assert meta.reaches["apply_vm_plan"] == policy_roles.REACHES["apply_vm_plan"]
|
|
49
|
+
assert "run_vm_guest_command" in meta.escapes
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
#: ops function a batch calls → the tool that does the same thing alone.
|
|
53
|
+
_OPS_TOOL = {
|
|
54
|
+
"clone_vm": "clone_vm",
|
|
55
|
+
"reconfigure_vm": "reconfigure_vm",
|
|
56
|
+
"create_snapshot": "create_vm_snapshot",
|
|
57
|
+
"power_on_vm": "power_on_vm",
|
|
58
|
+
"attach_iso": "attach_iso_to_vm",
|
|
59
|
+
"linked_clone": "deploy_linked_clone",
|
|
60
|
+
"deploy_from_template": "deploy_vm_from_template",
|
|
61
|
+
"deploy_ova": "deploy_vm_from_ova",
|
|
62
|
+
"create_vm": "create_vm",
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
#: batch tool → its ops function in vmware_aiops/ops/vm_deploy.py
|
|
66
|
+
_BATCH_OPS = {
|
|
67
|
+
"batch_clone_vms": "batch_clone",
|
|
68
|
+
"batch_linked_clone_vms": "batch_linked_clone",
|
|
69
|
+
"batch_deploy_from_spec": "batch_deploy",
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _calls_in(func_name: str) -> set[str]:
|
|
74
|
+
import ast
|
|
75
|
+
import inspect
|
|
76
|
+
|
|
77
|
+
from vmware_aiops.ops import vm_deploy
|
|
78
|
+
|
|
79
|
+
tree = ast.parse(inspect.getsource(getattr(vm_deploy, func_name)))
|
|
80
|
+
return {
|
|
81
|
+
n.func.id if isinstance(n.func, ast.Name) else n.func.attr
|
|
82
|
+
for n in ast.walk(tree)
|
|
83
|
+
if isinstance(n, ast.Call) and isinstance(n.func, (ast.Name, ast.Attribute))
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
@pytest.mark.unit
|
|
88
|
+
@pytest.mark.parametrize("tool", sorted(_BATCH_OPS))
|
|
89
|
+
def test_batch_reach_covers_every_step_it_runs(tool):
|
|
90
|
+
"""Review M1: a batch that also reconfigures/snapshots/powers on reaches those tools."""
|
|
91
|
+
called = _calls_in(_BATCH_OPS[tool])
|
|
92
|
+
reached = {_OPS_TOOL[c] for c in called if c in _OPS_TOOL}
|
|
93
|
+
assert reached, f"{_BATCH_OPS[tool]} calls none of the known ops; update _OPS_TOOL"
|
|
94
|
+
assert reached <= policy_roles.REACHES[tool], sorted(reached - policy_roles.REACHES[tool])
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
@pytest.mark.unit
|
|
98
|
+
def test_the_resolver_uses_the_config_the_connection_manager_holds(monkeypatch):
|
|
99
|
+
"""Review H1/H-1: once the server's connection manager exists, a config edit must
|
|
100
|
+
not move the role check off the config it connects with; before, read the file."""
|
|
101
|
+
import importlib
|
|
102
|
+
import types
|
|
103
|
+
|
|
104
|
+
from vmware_aiops import policy_roles as pr
|
|
105
|
+
|
|
106
|
+
server = importlib.import_module("vmware_aiops.mcp_server._shared")
|
|
107
|
+
assert hasattr(server, "_conn_mgr"), "policy_roles looks up a global the server does not have"
|
|
108
|
+
edited, loads = object(), []
|
|
109
|
+
monkeypatch.setattr(pr, "load_config", lambda: loads.append(1) or edited)
|
|
110
|
+
|
|
111
|
+
monkeypatch.setattr(server, "_conn_mgr", None)
|
|
112
|
+
assert pr._connection_config() is edited and pr._connection_config() is edited
|
|
113
|
+
assert len(loads) == 2 # no manager yet: the file as it is now, every time
|
|
114
|
+
|
|
115
|
+
held = object()
|
|
116
|
+
monkeypatch.setattr(server, "_conn_mgr", types.SimpleNamespace(_config=held))
|
|
117
|
+
assert pr._connection_config() is held # the manager's copy, not the edited file
|
|
@@ -1195,7 +1195,7 @@ wheels = [
|
|
|
1195
1195
|
|
|
1196
1196
|
[[package]]
|
|
1197
1197
|
name = "vmware-aiops"
|
|
1198
|
-
version = "2.
|
|
1198
|
+
version = "2.4.0"
|
|
1199
1199
|
source = { editable = "." }
|
|
1200
1200
|
dependencies = [
|
|
1201
1201
|
{ name = "apscheduler" },
|
|
@@ -1240,7 +1240,7 @@ dev = [
|
|
|
1240
1240
|
|
|
1241
1241
|
[[package]]
|
|
1242
1242
|
name = "vmware-monitor"
|
|
1243
|
-
version = "2.
|
|
1243
|
+
version = "2.4.0"
|
|
1244
1244
|
source = { editable = "../VMware-Monitor" }
|
|
1245
1245
|
dependencies = [
|
|
1246
1246
|
{ name = "apscheduler" },
|
|
@@ -1276,14 +1276,14 @@ dev = [
|
|
|
1276
1276
|
|
|
1277
1277
|
[[package]]
|
|
1278
1278
|
name = "vmware-policy"
|
|
1279
|
-
version = "1.
|
|
1279
|
+
version = "1.24.0"
|
|
1280
1280
|
source = { registry = "https://pypi.org/simple" }
|
|
1281
1281
|
dependencies = [
|
|
1282
1282
|
{ name = "pyyaml" },
|
|
1283
1283
|
{ name = "rich" },
|
|
1284
1284
|
{ name = "typer" },
|
|
1285
1285
|
]
|
|
1286
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
1286
|
+
sdist = { url = "https://files.pythonhosted.org/packages/4a/62/3a3cb83af77e3dd3c8fc92cb3b7968bfda04a2f71bf0d6f9b72ee3198441/vmware_policy-1.24.0.tar.gz", hash = "sha256:fba12732ccbd4371232c15d9fd014f9f5d697497210aedff2515d1d205ed3577", size = 361302, upload-time = "2026-10-16T07:18:28.317Z" }
|
|
1287
1287
|
wheels = [
|
|
1288
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1288
|
+
{ url = "https://files.pythonhosted.org/packages/3d/f2/fe3d9d384712023916e2cacddc385f14b095509c5e00aea417d1a9550e98/vmware_policy-1.24.0-py3-none-any.whl", hash = "sha256:cf615d0256134f01fb84c39b083649281a66d2c064c2eaa28786a0fa95ec6e58", size = 131460, upload-time = "2026-10-16T07:18:26.907Z" },
|
|
1289
1289
|
]
|
|
@@ -38,3 +38,6 @@ def _environment_for(target: str | None) -> str:
|
|
|
38
38
|
# to ALLOW. Keyed, a resolver only ever answers for its own skill, so
|
|
39
39
|
# registering at import time is safe again.
|
|
40
40
|
set_environment_resolver(_environment_for, skill=skill_name(__name__))
|
|
41
|
+
|
|
42
|
+
# Role metadata (HLD §18) is declared beside the environment resolver, on every surface.
|
|
43
|
+
import vmware_aiops.policy_roles # noqa: E402,F401
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"""What vmware-policy needs to apply roles to this skill (HLD §18 D-21/D-22).
|
|
2
|
+
|
|
3
|
+
Policy cannot see which tools run other tools, which tools escape a role, or how a
|
|
4
|
+
missing ``target`` resolves; this module declares them. Imported by
|
|
5
|
+
``policy_environment``, so the MCP server and the CLI both register it. With a
|
|
6
|
+
vmware-policy that has no roles module (< 1.24) nothing is declared.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import sys
|
|
12
|
+
|
|
13
|
+
from vmware_policy import skill_name
|
|
14
|
+
|
|
15
|
+
from vmware_aiops.config import load_config
|
|
16
|
+
|
|
17
|
+
#: Each plan action → the tool that does the same thing. ``reset``/``suspend`` have no
|
|
18
|
+
#: tool of their own; they change power state like ``power_off_vm``. The storage
|
|
19
|
+
#: actions are refused by ``plan_gate.REFUSED_ACTIONS`` and are not listed.
|
|
20
|
+
#: ``tests/test_policy_roles.py`` fails if a dispatch action is missing here.
|
|
21
|
+
ACTION_TOOLS: dict[str, str] = {
|
|
22
|
+
"attach_iso": "attach_iso_to_vm",
|
|
23
|
+
"clone": "clone_vm",
|
|
24
|
+
"cluster_add_host": "add_cluster_host",
|
|
25
|
+
"cluster_remove_host": "remove_cluster_host",
|
|
26
|
+
"configure_cluster": "configure_cluster",
|
|
27
|
+
"convert_to_template": "convert_vm_to_template",
|
|
28
|
+
"create_cluster": "create_cluster",
|
|
29
|
+
"create_snapshot": "create_vm_snapshot",
|
|
30
|
+
"create_vm": "create_vm",
|
|
31
|
+
"delete_cluster": "delete_cluster",
|
|
32
|
+
"delete_snapshot": "delete_vm_snapshot",
|
|
33
|
+
"delete_vm": "delete_vm",
|
|
34
|
+
"deploy_ova": "deploy_vm_from_ova",
|
|
35
|
+
"deploy_template": "deploy_vm_from_template",
|
|
36
|
+
"guest_download": "download_vm_guest_file",
|
|
37
|
+
"guest_exec": "run_vm_guest_command",
|
|
38
|
+
"guest_upload": "upload_vm_guest_file",
|
|
39
|
+
"linked_clone": "deploy_linked_clone",
|
|
40
|
+
"migrate": "migrate_vm",
|
|
41
|
+
"power_off": "power_off_vm",
|
|
42
|
+
"power_on": "power_on_vm",
|
|
43
|
+
"reconfigure": "reconfigure_vm",
|
|
44
|
+
"reset": "power_off_vm",
|
|
45
|
+
"revert_snapshot": "revert_vm_snapshot",
|
|
46
|
+
"suspend": "power_off_vm",
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
#: A plan's rollback deletes VMs the plan created, so applying or rolling back a plan
|
|
50
|
+
#: reaches ``delete_vm`` even when no step names it.
|
|
51
|
+
_PLAN_REACHES = frozenset(ACTION_TOOLS.values()) | {"delete_vm"}
|
|
52
|
+
|
|
53
|
+
REACHES: dict[str, frozenset[str]] = {
|
|
54
|
+
"apply_vm_plan": _PLAN_REACHES,
|
|
55
|
+
"rollback_vm_plan": _PLAN_REACHES,
|
|
56
|
+
"set_vm_ttl": frozenset({"delete_vm"}), # the scheduler deletes later, with no caller
|
|
57
|
+
# The batch tools run the follow-up steps their arguments ask for (review M1).
|
|
58
|
+
"batch_clone_vms": frozenset(
|
|
59
|
+
{"clone_vm", "reconfigure_vm", "create_vm_snapshot", "power_on_vm"}
|
|
60
|
+
),
|
|
61
|
+
"batch_linked_clone_vms": frozenset({"deploy_linked_clone"}),
|
|
62
|
+
"batch_deploy_from_spec": frozenset(
|
|
63
|
+
{
|
|
64
|
+
"deploy_vm_from_template",
|
|
65
|
+
"clone_vm",
|
|
66
|
+
"deploy_vm_from_ova",
|
|
67
|
+
"deploy_linked_clone",
|
|
68
|
+
"create_vm",
|
|
69
|
+
"reconfigure_vm",
|
|
70
|
+
"attach_iso_to_vm",
|
|
71
|
+
"create_vm_snapshot",
|
|
72
|
+
"power_on_vm",
|
|
73
|
+
}
|
|
74
|
+
),
|
|
75
|
+
"restore_vm_clean_slate": frozenset({"power_off_vm", "revert_vm_snapshot"}),
|
|
76
|
+
"provision_vm_guest": frozenset({"run_vm_guest_command", "upload_vm_guest_file"}),
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
#: Tools that give their holder more than a role: code in a guest, files on the
|
|
80
|
+
#: server host. (Host-path tools are added by policy while a file root is set.)
|
|
81
|
+
ESCAPES = frozenset(
|
|
82
|
+
{
|
|
83
|
+
"run_vm_guest_command",
|
|
84
|
+
"run_vm_guest_command_with_output",
|
|
85
|
+
"upload_vm_guest_file",
|
|
86
|
+
"download_vm_guest_file",
|
|
87
|
+
"provision_vm_guest",
|
|
88
|
+
}
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def _connection_config():
|
|
93
|
+
"""The config the connection layer uses for this call (review H1, then H-1).
|
|
94
|
+
|
|
95
|
+
The server's connection manager loads the config once, on its first connection,
|
|
96
|
+
and keeps it. Once it exists, the role is checked against that same object, so
|
|
97
|
+
an edit to config.yaml cannot move the check off the target the call connects
|
|
98
|
+
to. Before it exists, the file as it is now is what the manager is about to load.
|
|
99
|
+
Looked up in ``sys.modules`` so the CLI never imports the MCP server.
|
|
100
|
+
"""
|
|
101
|
+
server = sys.modules.get("vmware_aiops.mcp_server._shared")
|
|
102
|
+
manager = getattr(server, "_conn_mgr", None) if server is not None else None
|
|
103
|
+
return manager._config if manager is not None else load_config()
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def _target_name(target: str | None) -> str:
|
|
107
|
+
"""The target the connection layer would use for ``target`` (or the default)."""
|
|
108
|
+
config = _connection_config()
|
|
109
|
+
return (config.get_target(target) if target else config.default_target).name
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
try:
|
|
113
|
+
from vmware_policy.roles import declare_role_metadata
|
|
114
|
+
except ImportError: # vmware-policy without roles: nothing to declare
|
|
115
|
+
declare_role_metadata = None
|
|
116
|
+
|
|
117
|
+
if declare_role_metadata is not None:
|
|
118
|
+
declare_role_metadata(
|
|
119
|
+
skill_name(__name__),
|
|
120
|
+
escapes=ESCAPES,
|
|
121
|
+
reaches=REACHES,
|
|
122
|
+
resolver=_target_name,
|
|
123
|
+
)
|
|
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
|
{vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/skills/vmware-aiops/references/agent-guardrails.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/skills/vmware-aiops/references/investigation-protocol.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
|
|
File without changes
|
|
File without changes
|
{vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/capability/test_tool_description_quality.py
RENAMED
|
File without changes
|
{vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/capability/test_tool_manifest_budget.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/test_alarm_health_scale_n1.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/test_cli_destructive_guards.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/test_daemon_calls_are_audited.py
RENAMED
|
File without changes
|
{vmware_aiops-2.3.2 → vmware_aiops-2.4.0}/tests/eval/regression/test_daemon_host_log_cycles.py
RENAMED
|
File without changes
|