Initial commit: VMware vSphere API simulator scaffold.
Add the FastAPI app, PostgreSQL migrations, Docker/Helm packaging, API contracts, docs, client examples, and the unit/integration/compatibility test suite for local client and tooling labs without a real vCenter.
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
**Language / Язык:** [English](README.md) | [Русский](../ru/domains/README.md)
|
||||
|
||||
# Domain guides
|
||||
|
||||
These pages summarize durable semantics by area. For exhaustive method lists,
|
||||
use the Web UI catalog or OpenAPI (`/docs`), or browse
|
||||
[`app/vsphere/rest/coverage.py`](../../app/vsphere/rest/coverage.py) directly
|
||||
— the runtime always serves the full registered surface regardless of the
|
||||
active catalog major.
|
||||
|
||||
| Guide | Topics |
|
||||
|---|---|
|
||||
| [Session](session.md) | `/api/session`, legacy `/rest` session, SOAP `Login`/`Logout` |
|
||||
| [Inventory](inventory.md) | Datacenter, cluster, folder, resource pool, host, datastore, network CRUD |
|
||||
| [Virtual machines](vm.md) | Create/delete, power, hardware, snapshots, clone, relocate, guest ops |
|
||||
| [Storage](storage.md) | Datastores, files, host storage devices, storage policies |
|
||||
| [Networking](networking.md) | Standard/distributed portgroups, DVS, host networking |
|
||||
| [Tagging](tagging.md) | Categories, tags, associations |
|
||||
| [Content library](content-library.md) | Libraries, items, update/download sessions, OVF deploy |
|
||||
| [SOAP / VIM](soap.md) | RetrieveServiceContent, PropertyCollector, task-returning operations |
|
||||
| [Tasks](tasks.md) | CIS task ids, polling, workers |
|
||||
| [Appliance](appliance.md) | Version, health, networking, timesync |
|
||||
| [Authorization](authz.md) | Roles, privileges, permissions |
|
||||
|
||||
## Persistence map
|
||||
|
||||
- Inventory objects (hosts, VMs, datastores, networks, folders, …) →
|
||||
`vsphere_objects` (MOID, type, name, parent, `props` JSONB).
|
||||
- Sessions / credentials → `vsphere_sessions`, `vsphere_credentials`.
|
||||
- Tasks → `vsphere_tasks`.
|
||||
- Tags / categories / associations → `vsphere_tag_categories`,
|
||||
`vsphere_tags`, `vsphere_tag_associations`.
|
||||
- Content libraries / items → `vsphere_libraries`, `vsphere_library_items`.
|
||||
- Datastore file metadata → `vsphere_datastore_files`.
|
||||
- Remaining Broadcom Automation API routes (the DB-backed stub surface) →
|
||||
`vsphere_api_state` (migration `011`).
|
||||
- Content-library update/download sessions → `vsphere_transfer_sessions`
|
||||
(migration `012`).
|
||||
- HttpNfcLease transfer state → `vsphere_nfc_leases` (migration `012`).
|
||||
- PropertyCollector views / WaitForUpdates tokens → `vsphere_pc_state`
|
||||
(migration `013`).
|
||||
- Console tickets → `vsphere_console_tickets` (migration `013`).
|
||||
@@ -0,0 +1,35 @@
|
||||
**Language / Язык:** [English](appliance.md) | [Русский](../ru/domains/appliance.md)
|
||||
|
||||
# Appliance
|
||||
|
||||
vCenter Server Appliance (VCSA) surfaces — version, health, networking,
|
||||
timesync:
|
||||
[`app/vsphere/rest/appliance_ext.py`](../../app/vsphere/rest/appliance_ext.py),
|
||||
[`app/vsphere/domain/appliance.py`](../../app/vsphere/domain/appliance.py).
|
||||
|
||||
## Endpoints
|
||||
|
||||
| Method | Path | Notes |
|
||||
|---|---|---|
|
||||
| GET | `/api/appliance/system/version` | Readable without a session; reflects the active catalog major's label |
|
||||
| GET | `/api/appliance/health/system` | Overall health summary |
|
||||
| GET/PUT/POST | `/api/appliance/networking` | Hostname, DNS, default gateway, interfaces, proxy |
|
||||
| GET/PUT/POST | `/api/appliance/networking/dns/hostname` \| `/dns/servers` \| `/dns/domains` | Focused mirrors kept in sync with `/networking` |
|
||||
| GET | `/api/appliance/timesync` | NTP mode + servers |
|
||||
| GET | `/api/vcenter/certificate-management/vcenter/tls[-csr]` \| `/trusted-root-chains` | Machine-cert / CSR / trust-chain stand-ins |
|
||||
|
||||
## Highlights
|
||||
|
||||
- Defaults model a realistic single-nic VCSA (`vcenter.lab.local`,
|
||||
`192.168.1.50/24`, gateway `192.168.1.1`, `8.8.8.8`/`1.1.1.1` DNS).
|
||||
- `save_networking` keeps the focused DNS mirrors
|
||||
(`/dns/hostname`, `/dns/servers`, `/dns/domains`) consistent with the full
|
||||
`/networking` document so both shapes of Automation API client work.
|
||||
- State is idempotently seeded once per fresh database
|
||||
(`seed_appliance_state`) and persists in `vsphere_api_state`.
|
||||
- The TLS/certificate-management endpoints are seeded stand-ins, not a real
|
||||
VECS certificate store — see [API coverage](../api-coverage.md).
|
||||
|
||||
`/api/appliance/system/version` intentionally does not require a session in
|
||||
this lab build (real vCenter behavior varies by version) so smoke scripts can
|
||||
check availability before authenticating.
|
||||
@@ -0,0 +1,52 @@
|
||||
**Language / Язык:** [English](authz.md) | [Русский](../ru/domains/authz.md)
|
||||
|
||||
# Authorization
|
||||
|
||||
Role → privilege gate for REST mutate endpoints (and a decorator-style hook
|
||||
for SOAP): [`app/vsphere/security/authz.py`](../../app/vsphere/security/authz.py),
|
||||
[`platform_rest.py`](../../app/vsphere/rest/platform_rest.py).
|
||||
|
||||
## Endpoints
|
||||
|
||||
| Method | Path | Notes |
|
||||
|---|---|---|
|
||||
| GET | `/api/vcenter/privilege` | Privilege catalog |
|
||||
| GET | `/api/vcenter/authorization/roles` | Role → privilege set |
|
||||
| GET/POST/DELETE | `/api/vcenter/authorization/permissions[/{permission_id}]` | Principal ↔ role ↔ entity bindings |
|
||||
| GET/POST/PATCH/DELETE | `/api/vcenter/identity/providers[/{provider}]` | LocalOS + OIDC + SAML identity-provider stand-ins |
|
||||
|
||||
## Roles (seed)
|
||||
|
||||
| Role | Scope |
|
||||
|---|---|
|
||||
| `Administrator` | Every privilege in the catalog |
|
||||
| `ReadOnly` | `System.Anonymous`, `System.Read`, `System.View`, `Datastore.Browse` |
|
||||
| `VirtualMachinePowerUser` | Read + power/snapshot/clone interactions |
|
||||
| `VirtualMachineAdministrator` | Power-user set + create/delete/reconfigure/tag/content-library privileges |
|
||||
|
||||
`ROLE_PRIVILEGES` in `authz.py` defines the exact privilege sets; a
|
||||
non-exhaustive sample of gated privileges: `VirtualMachine.Inventory.Create`,
|
||||
`VirtualMachine.Inventory.Delete`, `VirtualMachine.Interact.PowerOn`,
|
||||
`VirtualMachine.Config.CPUCount`, `VirtualMachine.Provisioning.Clone`,
|
||||
`Datastore.FileManagement`, `Network.Assign`,
|
||||
`InventoryService.Tagging.CreateTag`, `ContentLibrary.AddLibraryItem`,
|
||||
`Authorization.ModifyPermissions`.
|
||||
|
||||
## How gating works
|
||||
|
||||
- `require_privilege(*needed)` is a FastAPI dependency factory: it resolves
|
||||
the session, loads roles (from the session or `vsphere_credentials` if
|
||||
absent), and raises HTTP 403 (`unauthorized`) if any listed privilege is
|
||||
missing.
|
||||
- `require_read` is shorthand for `require_privilege("System.Read")`.
|
||||
- Permissions can also scope a role to a specific entity MOID
|
||||
(`PermissionSpec(principal, role, entity_moid, propagate)`); the seed
|
||||
scopes `readonly@vsphere.local` to the datacenter and the two VM-admin
|
||||
principals to the VM folder.
|
||||
|
||||
## Seeded principals
|
||||
|
||||
See [Authentication](../authentication.md) for the four
|
||||
`@vsphere.local` principals and their roles, and
|
||||
[Seed profiles](../seed-profiles.md) for how permissions are scoped per
|
||||
profile.
|
||||
@@ -0,0 +1,38 @@
|
||||
**Language / Язык:** [English](content-library.md) | [Русский](../ru/domains/content-library.md)
|
||||
|
||||
# Content library
|
||||
|
||||
Local content libraries, library items, upload/download sessions, and OVF
|
||||
deploy:
|
||||
[`app/vsphere/rest/content_rest.py`](../../app/vsphere/rest/content_rest.py),
|
||||
[`nfc_rest.py`](../../app/vsphere/rest/nfc_rest.py),
|
||||
[`app/vsphere/domain/content.py`](../../app/vsphere/domain/content.py).
|
||||
|
||||
## Endpoints
|
||||
|
||||
| Method | Path | Notes |
|
||||
|---|---|---|
|
||||
| GET | `/api/content/library` | List library ids |
|
||||
| POST | `/api/content/local-library` | Create a local library |
|
||||
| GET/POST | `/api/content/library/item` | List / create items (`?library_id=`) |
|
||||
| POST | `/api/vcenter/ovf/library-item/{item_id}` | Deploy OVF item → new `VirtualMachine` + task |
|
||||
| POST | `/api/content/library/item/update-session[/{session_id}[/file]]` | Push-upload flow (Ansible/Terraform-style) |
|
||||
| GET/POST | `/api/content/library/item/download-session[/{session_id}[/file]]` | Pull-download flow |
|
||||
| GET/PUT/POST | `/nfc/{lease}` \| `/nfc/{lease}/files/{filename}` \| `/nfc/{lease}/complete` | HttpNfcLease-style transfer endpoints for the SOAP import path |
|
||||
|
||||
## Highlights
|
||||
|
||||
- Libraries/items persist in `vsphere_libraries` / `vsphere_library_items`;
|
||||
the seed creates two libraries ("Local Content", "Published Templates")
|
||||
with OVF-typed items (`ubuntu-22.04`, `centos-stream-9`, `golden-image`).
|
||||
- Update/download sessions persist in PostgreSQL (`vsphere_transfer_sessions`,
|
||||
migration `012`) and model the file-transfer handshake — not a real
|
||||
byte-for-byte OVF/VMDK store. HttpNfcLease rows live in `vsphere_nfc_leases`.
|
||||
- `deploy_ovf_from_library` creates a real `VirtualMachine` row and returns a
|
||||
task id, mirroring the SOAP `ImportVApp_Task` / `CreateImportSpec` +
|
||||
`HttpNfcLease*` flow used by govc-style `ovf.import`.
|
||||
- Requires `ContentLibrary.CreateLocalLibrary` / `.AddLibraryItem` to create,
|
||||
and `VirtualMachine.Provisioning.DeployTemplate` to deploy.
|
||||
|
||||
See [SOAP / VIM](soap.md) for the HttpNfcLease progress/complete/abort
|
||||
operations used by upload-heavy clients.
|
||||
@@ -0,0 +1,46 @@
|
||||
**Language / Язык:** [English](inventory.md) | [Русский](../ru/domains/inventory.md)
|
||||
|
||||
# Inventory
|
||||
|
||||
Datacenter, cluster, folder, resource pool, host, and datastore/network
|
||||
listing + CRUD:
|
||||
[`app/vsphere/rest/router.py`](../../app/vsphere/rest/router.py),
|
||||
[`app/vsphere/domain/inventory_ops.py`](../../app/vsphere/domain/inventory_ops.py).
|
||||
|
||||
## Endpoints
|
||||
|
||||
| Method | Path | Notes |
|
||||
|---|---|---|
|
||||
| GET | `/api/vcenter/datacenter` | List |
|
||||
| POST/DELETE | `/api/vcenter/datacenter[/{datacenter}]` | Create seeds host/vm/datastore/network sub-folders |
|
||||
| GET | `/api/vcenter/cluster` | List |
|
||||
| POST/DELETE | `/api/vcenter/cluster[/{cluster}]` | Create seeds a `ResourcePool` |
|
||||
| GET | `/api/vcenter/folder` | List; `GET /api/vcenter/folder/{folder}/children` |
|
||||
| POST/DELETE | `/api/vcenter/folder[/{folder}]` | |
|
||||
| GET | `/api/vcenter/resource-pool` | List |
|
||||
| POST/DELETE | `/api/vcenter/resource-pool[/{resource_pool}]` | |
|
||||
| GET | `/api/vcenter/host[/{host}]` | Connection state, CPU/memory, IP, storage devices, networking |
|
||||
| POST | `/api/vcenter/host/{host}/maintenance` | Toggle maintenance mode |
|
||||
| GET | `/api/vcenter/datastore[/{datastore}]` | Type, capacity, free space, accessibility |
|
||||
| GET | `/api/vcenter/network` | Standard networks + distributed portgroups |
|
||||
|
||||
Legacy `/rest/vcenter/*` mirrors most GET paths with a `{ "value": … }`
|
||||
envelope — see [API surface](../api-surface.md).
|
||||
|
||||
## Highlights
|
||||
|
||||
- Every inventory object is a row in `vsphere_objects` (MOID, type, name,
|
||||
`parent_moid`, `props` JSONB) — see
|
||||
[`app/vsphere/inventory.py`](../../app/vsphere/inventory.py).
|
||||
- MOID conventions follow real vCenter shapes: `datacenter-NN`,
|
||||
`domain-cNN` (cluster), `resgroup-NN` (resource pool), `group-vNN`/`group-hNN`/
|
||||
`group-sNN`/`group-nNN` (VM/host/datastore/network folders), `host-NN`,
|
||||
`datastore-NN`, `network-NN` / `dvportgroup-NN`.
|
||||
- `list_hosts`/`list_clusters`/etc. filter live PostgreSQL state; there is no
|
||||
separate cache to invalidate after a mutation.
|
||||
- VM listing (`GET /api/vcenter/vm`) supports filters: `names`,
|
||||
`power_states`, `hosts`, `folders`, `datacenters`, `clusters`,
|
||||
`resource_pools`, plus `limit`/`cursor` pagination.
|
||||
|
||||
See [Seed profiles](../seed-profiles.md) for the default topology shape and
|
||||
[Virtual machines](vm.md) for VM-specific operations.
|
||||
@@ -0,0 +1,35 @@
|
||||
**Language / Язык:** [English](networking.md) | [Русский](../ru/domains/networking.md)
|
||||
|
||||
# Networking
|
||||
|
||||
Standard networks, distributed portgroups/switches, and host networking:
|
||||
[`app/vsphere/rest/router.py`](../../app/vsphere/rest/router.py),
|
||||
[`platform_rest.py`](../../app/vsphere/rest/platform_rest.py).
|
||||
|
||||
## Endpoints
|
||||
|
||||
| Method | Path | Notes |
|
||||
|---|---|---|
|
||||
| GET | `/api/vcenter/network` | Standard `Network` objects + `DistributedVirtualPortgroup` |
|
||||
| GET/POST | `/api/vcenter/network/dvs` | Distributed virtual switches |
|
||||
| POST | `/api/vcenter/network/dvpg` | Create a distributed portgroup |
|
||||
| GET | `/api/vcenter/host/{host}/networking` | DNS, default gateway, `vmk0` interface, routing |
|
||||
| GET/PUT/POST | `/api/appliance/networking` \| `/networking/dns/{hostname,servers,domains}` | vCenter appliance-level networking (see [Appliance](appliance.md)) |
|
||||
|
||||
Legacy `GET /rest/vcenter/network` mirrors the list.
|
||||
|
||||
## Highlights
|
||||
|
||||
- Every VM's `nics[].value.backing` points at either a `STANDARD_PORTGROUP`
|
||||
(`network-41`, "VM Network") or a `DISTRIBUTED_PORTGROUP`
|
||||
(`dvportgroup-4N`, tagged with a `vlan_id`).
|
||||
- The default topology seeds one `VmwareDistributedVirtualSwitch`
|
||||
(`dvs-51`, `mtu: 9000`) and 1–3 extra distributed portgroups depending on
|
||||
profile size.
|
||||
- Host networking (`GET /api/vcenter/host/{host}/networking`) returns DNS
|
||||
servers/domains, a default gateway, and a single `vmk0` management
|
||||
interface with a deterministic IPv4 address per host index.
|
||||
- NSX-labelled Automation API paths (tier-0 gateway, projects, edges,
|
||||
VPC/subnets) are seeded lab stand-ins under `namespace-management` — see
|
||||
the "Platform surfaces" table in [API coverage](../api-coverage.md); they
|
||||
are not a real NSX Manager.
|
||||
@@ -0,0 +1,31 @@
|
||||
**Language / Язык:** [English](session.md) | [Русский](../ru/domains/session.md)
|
||||
|
||||
# Session
|
||||
|
||||
Durable session identity shared by REST and SOAP:
|
||||
[`app/vsphere/security/session.py`](../../app/vsphere/security/session.py).
|
||||
|
||||
## Endpoints
|
||||
|
||||
| Method | Path | Notes |
|
||||
|---|---|---|
|
||||
| POST | `/api/session` | Basic auth → JSON string session id + `vmware-api-session-id` header/cookie |
|
||||
| GET | `/api/session` | HTTP 200; `x-vmware-session-user` / `x-vmware-session-roles` headers |
|
||||
| DELETE | `/api/session` | Invalidates the session, clears cookie |
|
||||
| POST/GET/DELETE | `/rest/com/vmware/cis/session` | Legacy `{ "value": … }` equivalents |
|
||||
| POST | SOAP `SessionManager.Login` | Returns the same session id; sets `vmware_soap_session` cookie |
|
||||
| POST | SOAP `SessionManager.Logout` | Deletes the session |
|
||||
|
||||
## Highlights
|
||||
|
||||
- Sessions are opaque 32-char hex tokens stored in `vsphere_sessions` with a
|
||||
**2-hour sliding TTL** — every authenticated call extends `expires_at`.
|
||||
- The four lab credentials (`vsphere_credentials`, scrypt-hashed) are
|
||||
idempotently ensured on first login and by every seed profile
|
||||
(`ensure_default_credentials`).
|
||||
- `require_session` resolves the session from either the
|
||||
`vmware-api-session-id` header or cookie; missing/expired → HTTP 401.
|
||||
- Roles are attached to the session at lookup time
|
||||
(`vsphere_credentials.roles`) and drive [Authorization](authz.md).
|
||||
|
||||
See [Authentication](../authentication.md) for full request examples.
|
||||
@@ -0,0 +1,68 @@
|
||||
**Language / Язык:** [English](soap.md) | [Русский](../ru/domains/soap.md)
|
||||
|
||||
# SOAP / VIM
|
||||
|
||||
Minimal VIM SDK for pyvmomi / govmomi-style clients (Terraform's
|
||||
`hashicorp/vsphere` provider, Pulumi, govc):
|
||||
[`app/vsphere/soap/router.py`](../../app/vsphere/soap/router.py),
|
||||
[`property_collector.py`](../../app/vsphere/soap/property_collector.py),
|
||||
[`pbm.py`](../../app/vsphere/soap/pbm.py).
|
||||
|
||||
## Endpoint
|
||||
|
||||
All operations POST a SOAP envelope to `/sdk` (also `/sdk/`). Auxiliary
|
||||
routes:
|
||||
|
||||
| Method | Path | Notes |
|
||||
|---|---|---|
|
||||
| GET | `/sdk/vimService.wsdl` (alias `/sdk/vim.wsdl`) | WSDL stub advertising the implemented operation list |
|
||||
| GET | `/sdk/about.do` (alias `/about.do`) | Human-readable "VMware vCenter Server" page |
|
||||
| POST | `/sdk/vim25/{version}/SessionManager/SessionManager/Login` | JSON-body login variant used by some SDKs |
|
||||
|
||||
## Implemented operations
|
||||
|
||||
- `RetrieveServiceContent`, `Login`, `Logout`
|
||||
- `RetrieveProperties`, `RetrievePropertiesEx`, **ContinueRetrievePropertiesEx**
|
||||
(pagination tokens; `<objects>` plural), `CreateFilter`,
|
||||
`WaitForUpdatesEx` (version tokens; empty polls), `CreateContainerView`,
|
||||
`DestroyPropertyFilter`
|
||||
- `FindByInventoryPath` (paths omit the root `Datacenters` folder, matching
|
||||
govmomi conventions), `FindByUuid`, `FindByDnsName`, `FindByIp`, `FindChild`
|
||||
- `CreateVM_Task`, `CreateChildVM_Task`, `CreateFolder`, `PowerOnVM_Task`,
|
||||
`PowerOffVM_Task`, `CloneVM_Task`, `CreateSnapshot_Task`, `Rename_Task`,
|
||||
`ReconfigVM_Task`, `RelocateVM_Task`, `Destroy_Task`, `CustomizeVM_Task`,
|
||||
`CancelTask`, `CurrentTime`
|
||||
- Guest file ops: `InitiateFileTransferToGuest`,
|
||||
`InitiateFileTransferFromGuest`, `ListFilesInGuest`, `DeleteFileInGuest`,
|
||||
`MakeDirectoryInGuest`
|
||||
- Import/upload: `ImportVApp_Task`, `CreateImportSpec`,
|
||||
`HttpNfcLeaseComplete`, `HttpNfcLeaseProgress`, `HttpNfcLeaseAbort`,
|
||||
`HttpNfcLeaseGetManifest` (paired with the REST `/nfc/{lease}` endpoints —
|
||||
see [Content library](content-library.md))
|
||||
- `QueryConfigOption`, `QueryConfigOptionEx`, `QueryConfigOptionDescriptor`,
|
||||
`QueryConfigTarget`
|
||||
- PBM (`/pbm`) stub for storage-policy-aware clients
|
||||
|
||||
## Highlights
|
||||
|
||||
- `Login` issues the same underlying session as REST (`vmware-api-session-id`
|
||||
cookie/header, plus a `vmware_soap_session` cookie) — see
|
||||
[Session](session.md).
|
||||
- `VIM_VERSION` is pinned to `8.0.2` with ≤3 dotted components, since
|
||||
`hashicorp/vsphere` parses `AboutInfo.version` strictly.
|
||||
- Type-strict MOR lookup rejects a `VirtualApp:resgroup-*` reference from
|
||||
resolving as a plain `ResourcePool` — matters for the Terraform
|
||||
`CreateVM_Task` resource path.
|
||||
- Task-returning operations create a real row in `vsphere_tasks` (shared with
|
||||
REST — see [Tasks](tasks.md)), including `info.result` MoRefs on
|
||||
create/clone.
|
||||
- PropertyCollector filters, ContainerViews, and WaitForUpdatesEx version
|
||||
tokens persist in `vsphere_pc_state` (migration `013`) across process
|
||||
restarts within a lab.
|
||||
- `Folder.childType` is emitted as `ArrayOfString`; string properties carry
|
||||
`xsi:type="xsd:string"` so govmomi's decoder accepts them; `Datastore.host`
|
||||
is `ArrayOfDatastoreHostMount`; `Cluster`/`Host` expose `environmentBrowser`.
|
||||
|
||||
See [Clients](../clients.md) for pyvmomi/govmomi/Terraform/Pulumi connection
|
||||
examples and [examples/python/vsphere_soap_smoke.py](../../examples/python/vsphere_soap_smoke.py)
|
||||
for a minimal raw-XML smoke.
|
||||
@@ -0,0 +1,37 @@
|
||||
**Language / Язык:** [English](storage.md) | [Русский](../ru/domains/storage.md)
|
||||
|
||||
# Storage
|
||||
|
||||
Datastores, datastore file metadata, host storage devices, and storage
|
||||
policies:
|
||||
[`app/vsphere/rest/router.py`](../../app/vsphere/rest/router.py),
|
||||
[`content_rest.py`](../../app/vsphere/rest/content_rest.py),
|
||||
[`platform_rest.py`](../../app/vsphere/rest/platform_rest.py),
|
||||
[`app/vsphere/domain/content.py`](../../app/vsphere/domain/content.py).
|
||||
|
||||
## Endpoints
|
||||
|
||||
| Method | Path | Notes |
|
||||
|---|---|---|
|
||||
| GET | `/api/vcenter/datastore[/{datastore}]` | Type (`VMFS`/`NFS`), capacity, free space, `multiple_host_access` |
|
||||
| GET/POST | `/api/vcenter/datastore/{datastore}/files` | List / register file metadata (ISOs, VMX, VMDK paths) |
|
||||
| GET | `/api/vcenter/host/{host}/storage/storage-device` | Seeded local disk devices (`naa.*`, capacity, SSD flag) |
|
||||
| GET | `/api/vcenter/storage/policies[/{policy}/vm]` | Storage-based policy management, incl. `policy_type: VSAN` lab policies |
|
||||
|
||||
Legacy `GET /rest/vcenter/datastore` mirrors the list in a
|
||||
`{ "value": … }` envelope.
|
||||
|
||||
## Highlights
|
||||
|
||||
- Datastore rows are seeded with realistic capacity/free-space pairs
|
||||
(`type`, `capacity`, `free_space`, `accessible`,
|
||||
`multiple_host_access`) — see
|
||||
[`app/vsphere/profiles.py`](../../app/vsphere/profiles.py).
|
||||
- File metadata lives in `vsphere_datastore_files` (`path`, `size`, `type`);
|
||||
the seed pre-populates ISOs and a VM's `.vmx`/`.vmdk` entries
|
||||
(`seed_platform_extras`).
|
||||
- Storage policies include a lab `RAID1` vSAN-labelled policy — see the
|
||||
"Platform surfaces" table in [API coverage](../api-coverage.md) for the
|
||||
vSAN caveat (seeded lab data, not a real vSAN cluster).
|
||||
- Host storage devices are per-host synthetic disks, not real ESXi VMFS
|
||||
extents — capacity/SSD flags vary deterministically by host index.
|
||||
@@ -0,0 +1,31 @@
|
||||
**Language / Язык:** [English](tagging.md) | [Русский](../ru/domains/tagging.md)
|
||||
|
||||
# Tagging
|
||||
|
||||
CIS tagging service (categories, tags, object associations):
|
||||
[`app/vsphere/rest/tagging_rest.py`](../../app/vsphere/rest/tagging_rest.py),
|
||||
[`app/vsphere/domain/tagging.py`](../../app/vsphere/domain/tagging.py).
|
||||
|
||||
## Endpoints
|
||||
|
||||
| Method | Path | Notes |
|
||||
|---|---|---|
|
||||
| GET/POST | `/api/cis/tagging/category` | List / create (`cardinality`, `associable_types`) |
|
||||
| GET/DELETE | `/api/cis/tagging/category/{category_id}` | |
|
||||
| GET/POST | `/api/cis/tagging/tag` | List / create under a category |
|
||||
| GET/DELETE | `/api/cis/tagging/tag/{tag_id}` | |
|
||||
| POST | `/api/cis/tagging/tag-association` | Attach/detach a tag to/from an object |
|
||||
|
||||
## Highlights
|
||||
|
||||
- Category and tag ids follow the real `urn:vmomi:InventoryServiceCategory:…`
|
||||
/ `urn:vmomi:InventoryServiceTag:…:GLOBAL` shape.
|
||||
- Rows persist in `vsphere_tag_categories`, `vsphere_tags`,
|
||||
`vsphere_tag_associations` — durable across restarts, replaced on reseed.
|
||||
- The seed creates two categories (`Environment`, `Owner`) with `prod`/
|
||||
`staging`/`platform` tags and attaches `prod` to two seeded VMs
|
||||
(`seed_platform_extras` in
|
||||
[`app/vsphere/domain/content.py`](../../app/vsphere/domain/content.py)).
|
||||
- Attaching/creating a tag requires
|
||||
`InventoryService.Tagging.CreateCategory` / `.CreateTag` / `.AttachTag`
|
||||
privileges — see [Authorization](authz.md).
|
||||
@@ -0,0 +1,37 @@
|
||||
**Language / Язык:** [English](tasks.md) | [Русский](../ru/domains/tasks.md)
|
||||
|
||||
# Tasks
|
||||
|
||||
Long-running operations (power, clone, relocate, snapshot, OVF deploy, guest
|
||||
customize) return a CIS-style task id:
|
||||
[`app/vsphere/domain/tasks.py`](../../app/vsphere/domain/tasks.py),
|
||||
[`app/vsphere/rest/tasks.py`](../../app/vsphere/rest/tasks.py).
|
||||
|
||||
## Endpoints
|
||||
|
||||
| Method | Path | Notes |
|
||||
|---|---|---|
|
||||
| GET | `/api/cis/tasks` | List recent tasks (most recent 200) |
|
||||
| GET | `/api/cis/tasks/{task}` | Status, progress, `service`/`operation`, `result`/`error` |
|
||||
|
||||
## Client pattern
|
||||
|
||||
1. `POST`/`DELETE` mutation → read the task id from `{ "task": "task-…" }`
|
||||
(REST) or the SOAP `*_Task` MoRef.
|
||||
2. Poll `GET /api/cis/tasks/{task}` until `status` is `SUCCEEDED` or `FAILED`.
|
||||
3. `result` holds operation-specific output (for example `{"vm": "vm-104"}`
|
||||
on create/clone/deploy).
|
||||
|
||||
## Highlights
|
||||
|
||||
- Task rows commit to `vsphere_tasks` (`id`, `description`, `status`,
|
||||
`service`, `operation`, `result`, `error`, `completed_at`).
|
||||
- `progress` is synthesized as `50` while running and `100` once terminal —
|
||||
this simulator does not model fractional progress.
|
||||
- The same task store backs both REST `/api/cis/tasks` and SOAP task MoRefs,
|
||||
so a Terraform apply (SOAP `CreateVM_Task`) and a REST poll of the same id
|
||||
see consistent state.
|
||||
- Simulation durations honour `SIMULATION_TIME_SCALE`
|
||||
(higher = faster simulated completion).
|
||||
|
||||
See [API surface](../api-surface.md) and [Operations](../operations.md).
|
||||
@@ -0,0 +1,50 @@
|
||||
**Language / Язык:** [English](vm.md) | [Русский](../ru/domains/vm.md)
|
||||
|
||||
# Virtual machines
|
||||
|
||||
Full REST lifecycle for `VirtualMachine` objects:
|
||||
[`app/vsphere/rest/router.py`](../../app/vsphere/rest/router.py),
|
||||
[`vm_ext.py`](../../app/vsphere/rest/vm_ext.py),
|
||||
[`app/vsphere/domain/vm_ops.py`](../../app/vsphere/domain/vm_ops.py).
|
||||
|
||||
## Endpoints
|
||||
|
||||
| Method | Path | Notes |
|
||||
|---|---|---|
|
||||
| GET | `/api/vcenter/vm` | List with `names`/`power_states`/`hosts`/`folders`/`datacenters`/`clusters`/`resource_pools`/`limit`/`cursor` filters |
|
||||
| GET/DELETE | `/api/vcenter/vm/{vm}` | Get / delete (must be powered off) |
|
||||
| POST | `/api/vcenter/vm` | Create — `placement.{folder,host,datastore,resource_pool}`, `cpu.count`, `memory.size_MiB`, `disks`, `nics` |
|
||||
| GET/POST | `/api/vcenter/vm/{vm}/power` | Get power state / `?action=start\|stop\|suspend\|reset` — returns `{ "task": "task-…" }` |
|
||||
| GET | `/api/vcenter/vm/{vm}/hardware` | Summary |
|
||||
| GET/PATCH | `/api/vcenter/vm/{vm}/hardware/cpu` \| `/memory` | Change CPU count / memory (privilege-gated) |
|
||||
| GET/POST | `/api/vcenter/vm/{vm}/hardware/disk` \| `/ethernet` | Add disk / NIC |
|
||||
| GET | `/api/vcenter/vm/{vm}/hardware/boot` | Boot type/order |
|
||||
| GET/POST/DELETE | `/api/vcenter/vm/{vm}/snapshots[/{snapshot}]` | Create, revert (`?action=revert`), delete |
|
||||
| POST | `/api/vcenter/vm/{vm}/clone` \| `/relocate` | Task-returning |
|
||||
| GET/POST | `/api/vcenter/vm/{vm}/tools` | Guest tools status / upgrade |
|
||||
| GET | `/api/vcenter/vm/{vm}/guest/identity` \| `/networking` | Guest OS name, synthetic IP |
|
||||
| GET/POST | `/api/vcenter/vm/{vm}/guest/power` | Guest-level power ops |
|
||||
| POST | `/api/vcenter/vm/{vm}/guest/customization` | Sysprep/cloud-init-style customization spec |
|
||||
| POST | `/api/vcenter/vm/{vm}/console/tickets` | Console (VNC/WebMKS-style) ticket |
|
||||
| GET/PUT/DELETE | `/api/vcenter/vm/{vm}/guest/filesystem` | Lab virtual guest filesystem (Ansible/Terraform write-a-file flows) |
|
||||
| GET | `/api/vcenter/vm/{vm}/guest/filesystem/files` \| `/guest/local-filesystem` | Listing |
|
||||
|
||||
## Highlights
|
||||
|
||||
- Every VM row carries a realistic device shape: `nics`, `disks`, `cdroms`,
|
||||
`floppies`, `serials`, `scsi_adapters`, `boot`/`boot_devices`, `identity`
|
||||
(`instance_uuid`, `bios_uuid`), and a synthetic `guest_ip` /
|
||||
`guest_filesystems` map — the same fields power both the REST hardware
|
||||
endpoints and SOAP `VirtualMachineConfigInfo`.
|
||||
- Create requires `VirtualMachine.Inventory.Create`; delete requires
|
||||
`VirtualMachine.Inventory.Delete` **and** the VM must be `POWERED_OFF`.
|
||||
- Power/clone/snapshot/relocate/customize all create a durable CIS task (see
|
||||
[Tasks](tasks.md)) rather than mutating synchronously in the response body.
|
||||
- Console tickets from `/api/vcenter/vm/{vm}/console/tickets` persist in
|
||||
`vsphere_console_tickets` (migration `013`).
|
||||
- MOIDs follow the `vm-{100+n}` convention seeded by
|
||||
[`app/vsphere/profiles.py`](../../app/vsphere/profiles.py).
|
||||
|
||||
See [Storage](storage.md) for datastore/disk-file semantics and
|
||||
[SOAP / VIM](soap.md) for the equivalent `CreateVM_Task`/`PowerOnVM_Task`/…
|
||||
operations used by pyvmomi, govmomi, Terraform, and Pulumi.
|
||||
Reference in New Issue
Block a user