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:
2026-07-18 04:42:11 +03:00
commit f8d3cbdd59
422 changed files with 361335 additions and 0 deletions
+32
View File
@@ -0,0 +1,32 @@
**Language / Язык:** [English](../README.md) | [Русский](README.md)
# Документация
Руководства по симулятору VMware vSphere API. Переключайте язык с помощью заголовка на
каждой странице. Русские версии находятся в каталоге [`ru/`](README.md).
| Руководство | Описание |
|---|---|
| [Быстрый старт](getting-started.md) | Первая успешная лабораторная сессия |
| [Конфигурация](configuration.md) | Переменные окружения и Compose |
| [Аутентификация](authentication.md) | Сессии, `vmware-api-session-id`, привилегии |
| [Версии API](api-versions.md) | Catalog majors 69 и hot-swap |
| [Поверхность API](api-surface.md) | Маршрутизация REST/SOAP, coverage registry, stubs |
| [Покрытие API](api-coverage.md) | Broadcom universe vs реализованная поверхность |
| [Клиенты и примеры](clients.md) | Python, Go, Java, Perl, Ansible, Terraform, Pulumi |
| [Профили seed](seed-profiles.md) | Детерминированные фикстуры инвентаря |
| [Домены](domains/README.md) | Session, inventory, VM, storage, networking, tagging, SOAP, tasks, … |
| [Web UI](web-ui.md) | Интерактивная консоль и каталоги |
| [Эксплуатация](operations.md) | Reseed, migrate, release, upgrade |
| [Kubernetes / Helm](kubernetes.md) | Образ Hub + Ingress + Let's Encrypt |
| [Безопасность](security.md) | Модель угроз лаборатории и учётные данные |
| [Наблюдаемость](observability.md) | Эндпоинты health и логирование |
| [Порты](ports.md) | Опубликованные порты хоста и внутренние сервисы |
| [Устранение неполадок](troubleshooting.md) | Типичные сбои |
| [FAQ](faq.md) | Краткие ответы |
| [Архитектура](architecture.md) | Границы компонентов |
| [Совместимость](compatibility.md) | Модель evidence и матрица релизов |
Исполняемые cookbook'и: [`examples/`](../../examples/README.ru.md).
Интеграционные наборы: [`pulumi-tests/`](../../pulumi-tests/README.ru.md)
(`make pulumi-tests`).
+167
View File
@@ -0,0 +1,167 @@
**Language / Язык:** [English](../api-coverage.md) | [Русский](api-coverage.md)
# Матрица покрытия vSphere API
Реестр, ориентированный на автоматизацию: [`app/vsphere/rest/coverage.py`](../../app/vsphere/rest/coverage.py).
Стабы universe от Broadcom: [`app/vsphere/rest/universe.json`](../../app/vsphere/rest/universe.json) (из публичного индекса операций).
Уровни по мажорам + бандлы стаб-OpenAPI: [`app/vsphere/contracts/matrix.py`](../../app/vsphere/contracts/matrix.py) → `contracts/vsphere/<version>/manifest.json`.
## Broadcom в сравнении с этим симулятором
Публичный источник (собран скрапингом): [Индекс операций vSphere Automation API (9.1 Latest)](https://developer.broadcom.com/xapis/vsphere-automation-api/latest/operation-index/)
| Поверхность | Количество | Примечания |
|---|---:|---|
| Индекс операций Broadcom | **1348** | GET 628 / POST 422 / DELETE 114 / PUT 93 / PATCH 91 |
| Сгенерированные уникальные маршруты `verb + path` | **~1037** | Один и тот же HTTP-путь может обслуживать несколько именованных операций (`?action=…`, `$Task`) |
| Реестр симулятора (core + стабы + `/rest`) | **1077** | Глубокие core-обработчики перезаписывают записи стабов на том же пути |
| Глубокие core-обработчики | **104** | Поведение seeded-инвентаря / жизненного цикла / authz |
| Строки поверхности, поддерживаемые БД (`vsphere_api_state`) | **~540+** | Загружаются seed для каждого GET-маршрута `/api` + лабораторные дополнения |
Регенерируйте universe после обновления дампа индекса:
```bash
python scripts/generate_vsphere_universe.py
make vsphere-bundles
```
Обновление живой статистики / регенерация артефактов:
```bash
curl -sk https://localhost/ui/api/compatibility?major=9
make vsphere-surface
python scripts/write_vsphere_bundles.py
python scripts/write_vsphere_evidence.py
```
| Мажор | Метка | Реализовано / universe | Покрытие | Примечания |
|---|---|---:|---:|---|
| 6 | vSphere 7.0 | 31 / 1077 | 2.9% | Только floor каталога/evidence |
| 7 | vSphere 7.0 U3 | 77 / 1077 | 7.2% | Только floor каталога/evidence |
| 8 | vSphere 8.0 | 103 / 1077 | 9.6% | Только floor каталога/evidence |
| 9 | vSphere 8.0 U2 / поверхность Automation 9.1 | **1077 / 1077** | **100%** | Глубокие обработчики + DB-backed поверхность Broadcom |
Числа берутся из `GET /ui/api/compatibility?major=N` и
`evidence/vsphere-*.json` (`make vsphere-bundles`).
Hot-swap (`POST /ui/api/contract/apply?major=N`) меняет **catalog** major для
Web UI / evidence-отчётов. **Runtime всегда обслуживает полную
зарегистрированную поверхность** — известные пути не получают HTTP 501 из-за
version floor.
## Плоскости
| Плоскость | По умолчанию | Примечания |
|---|---|---|
| Native REST `/api`, `/rest` | включена | Основная лабораторная поверхность |
| Native SOAP `/sdk` | включена | Подмножество PropertyCollector + задачи ВМ |
| Стаб Proxmox `/api2/*` | **выключена** (`ENABLE_PVE_STUB=false`) | Опциональный legacy |
## Auth и синтетические данные
| Пункт | Детали |
|---|---|
| Пользователи | `administrator`, `readonly`, `operator`, `vmadmin` `@vsphere.local` / `VMware1!` |
| AuthZ | Проверка привилегий по роли на мутирующих эндпоинтах (403 `unauthorized`) |
| Seed `large` | 10 хостов, **1000 ВМ**, 4 datastore, DVS, папки, права |
| Seed `demo-cluster` | 20 хостов, 1000 ВМ (загрузка demo в UI) |
| Seed `small` | 3 хоста, 5 именованных ВМ (тесты) |
## Домены REST
### Глубокие (core) на мажоре 9
- Сессия / задачи CIS / роли+права AuthZ / провайдеры идентичности / стаб TLS-сертификата
- Список/получение/создание/удаление/power ВМ, оборудование, снапшоты,
клонирование, relocate, tools, идентичность/сети/питание/customization
гостя, консольные тикеты, template/unregister
- Список/получение хостов + maintenance + storage-device + сети
- Список/получение datastore + метаданные файлов
- Список сетей + создание DVS/DVPG
- CRUD для datacenter / cluster / folder (+ дети) / resource-pool
- Тегирование, content library + OVF, политики хранения (+ привязки к ВМ), привилегии
- Версия/health/сети/timesync appliance
- Стаб списка сервисов метамодели `vapi`
### DB-backed поверхность Automation (catch-all universe Broadcom)
Оставшиеся маршруты Automation API из индекса операций 9.1 зарегистрированы
и обслуживаются [`app/vsphere/rest/stub_surface.py`](../../app/vsphere/rest/stub_surface.py) против PostgreSQL:
- таблица `vsphere_api_state` (миграция `011_vsphere_api_state.sql`)
- seed через `seed_api_surface()` при каждом профиле, включая
**`demo-cluster`** / UI `POST /ui/api/demo/load`
- overlay инвентаря для оборудования ВМ (cdrom/scsi/boot/…), сетей/хранения
хоста, тегирования, content library
- PUT/PATCH сохраняются в `vsphere_api_state`; POST добавляет строки
коллекции; DELETE их удаляет
Нет маркеров `"stub": true` — зондам нужны реальные seeded-payload'ы на
мажоре 9.
## Домены SOAP (govmomi / Terraform / Pulumi / pyvmomi)
- RetrieveServiceContent (+ TaskManager / SearchIndex / GuestOperationsManager / FileManager / OvfManager)
- RetrieveProperties / RetrievePropertiesEx / **ContinueRetrievePropertiesEx** (токены пагинации; `<objects>` во множественном числе)
- PropertyCollector: цепочка предков Ancestors, однохоповый `childEntity`
ListFolder, обход ContainerView `view`
- `Folder.childType` как `ArrayOfString`; строковые свойства несут
`xsi:type="xsd:string"` (декодирование govmomi)
- `Datastore.host` как `ArrayOfDatastoreHostMount`; **environmentBrowser** у
Cluster/Host
- **QueryConfigOption** / QueryConfigOptionEx / QueryConfigOptionDescriptor / QueryConfigTarget
- CreateFilter / WaitForUpdatesEx (токены версий; пустые опросы)
- FindByInventoryPath (пути govmomi не включают корневую `Datacenters`),
FindByUuid/Dns/Ip, FindChild
- **CreateVM_Task** / CreateChildVM_Task, CreateFolder,
Power/Clone/Snapshot/Rename/Reconfig/Relocate/Destroy/Unregister/MarkAsTemplate/CustomizeVM_Task + CancelTask
- Файловые операции гостя: ListFilesInGuest,
InitiateFileTransferTo/FromGuest, DeleteFileInGuest, MakeDirectoryInGuest
- Реальные ID задач из `vsphere_tasks` (включая MoRef в `info.result` при
create/clone)
- `/sdk/vimService.wsdl`, `/sdk/about.do`, стаб `/pbm`
- Строгий по типам поиск MOR: `VirtualApp:resgroup-*` не резолвится как
обычный ResourcePool (путь CreateVM в Terraform)
## Дополнения REST для Ansible / Python-приложений
- Power ВМ возвращает `{ "task": "task-…" }` для опроса задач CIS
- Виртуальная файловая система гостя:
`/api/vcenter/vm/{vm}/guest/filesystem` (+ листинг локальной файловой
системы)
- Сессии обновления/загрузки content library для лабораторных потоков
push/pull OVF
## Legacy `/rest`
Обёртки `{ "value": … }` для
vm/host/datastore/network/datacenter/cluster/power/appliance.
## Мажоры контракта (browse в сравнении с runtime)
Hot-swap (`POST /ui/api/contract/apply?major=N`) всё ещё переключает мажор
**каталога** для просмотра/evidence в UI. **Runtime всегда обслуживает
полную зарегистрированную поверхность** глубокими обработчиками или
DB-backed стабами — известные пути никогда не получают HTTP 501 из-за
уровня версии. Уровни каталога остаются историческими только для
документации.
## Поверхности платформы (доступны в лаборатории)
Исторически они считались «отложенными»; теперь они возвращают
**непустые seeded лабораторные данные** и принимают базовые мутации:
| Область | REST | SOAP |
|---|---|---|
| NSX (tier0 / проекты / edges / VPC / подсети) | Seeded-пути Automation под `namespace-management` / `namespaces` | — |
| Supervisor / WCP | namespace, классы ВМ, сводка/идентичность supervisor, политики инфраструктуры | — |
| vSAN | Политики хранения с `policy_type: VSAN` (+ лабораторная политика RAID1) | — |
| SAML / OIDC | `GET/POST/PATCH/DELETE /api/vcenter/identity/providers` (LocalOS + OIDC + SAML) | — |
| VECS / сертификаты | TLS, CSR TLS, доверенные цепочки корней, сертификаты/запросы подписи supervisor | — |
| HttpNfcLease | `PUT/GET /nfc/{lease}/files/...` | `ImportVApp_Task`, `CreateImportSpec`, ход/завершение lease |
| Customization гостя | GET+POST `/api/vcenter/vm/{vm}/guest/customization` | `CustomizeVM_Task` |
Это всё ещё **лабораторный** заменитель (не бинарно совместимый с NSX
Manager / не настоящее хранилище VECS / не полная матрица XML устройств
Broadcom). Perf/Event/Alarm по-прежнему отвечают, но не симулируются
глубоко.
+91
View File
@@ -0,0 +1,91 @@
**Language / Язык:** [English](../api-surface.md) | [Русский](api-surface.md)
# Поверхность API
## Путь запроса
1. Middleware назначает или пересылает ID запроса (`REQUEST_ID_HEADER`).
2. FastAPI направляет запрос в роутер vSphere REST (`/api`, `/rest`), роутер
SOAP (`/sdk`) или (если `ENABLE_PVE_STUB=true`) в опциональный legacy-стаб.
3. `/api/session` (либо `/rest/com/vmware/cis/session`, либо SOAP `Login`)
определяет принципала и выдаёт `vmware-api-session-id`.
4. Зависимости `require_read` / `require_privilege(...)` проверяют роли
сессии перед раскрытием или мутацией ресурсов.
5. Глубокий обработчик (базовая логика инвентаря/жизненного цикла/тегов/
контента/appliance) или DB-backed поверхность стабов выполняется против
состояния, хранимого в PostgreSQL.
6. Долгие операции (power, clone, relocate, snapshot, деплой OVF) создают
долговечную CIS-задачу и возвращают `{ "task": "task-…" }`.
## Две REST-поверхности в одном реестре
- **Core (глубокие) обработчики** — ~104 комбинации verb+path в
[`app/vsphere/rest/router.py`](../../app/vsphere/rest/router.py),
`vm_ext.py`, `inventory_ext.py`, `platform_rest.py`, `tagging_rest.py`,
`content_rest.py`, `appliance_ext.py`, `nfc_rest.py`, `tasks.py`. Они
читают и мутируют напрямую seeded-таблицы инвентаря/тегов/контента/
appliance.
- **DB-backed поверхность стабов** —
[`app/vsphere/rest/stub_surface.py`](../../app/vsphere/rest/stub_surface.py)
отвечает на оставшиеся маршруты индекса операций Broadcom Automation API
(зарегистрированные из `universe.json`) против `vsphere_api_state`. GET
возвращает живые payload'ы, производные от инвентаря, когда это возможно,
иначе — seeded-строки; PUT/PATCH сохраняются в `vsphere_api_state`; POST
добавляет строки коллекции; DELETE их удаляет. Маркер `"stub": true` не
возвращается — зонды видят реальные seeded-payload'ы.
Обе поверхности используют одну таблицу маршрутов; core-обработчики имеют
приоритет над записями стабов, зарегистрированными для того же verb+path.
## Legacy `/rest`
[`app/vsphere/rest/legacy.py`](../../app/vsphere/rest/legacy.py) оборачивает
чтения vm/host/datastore/network/datacenter/cluster/power/appliance (и
power ВМ) в конверты `{ "value": … }` для более старых клиентов
`com.vmware.vcenter.*`.
## Ошибки ([`app/vsphere/errors.py`](../../app/vsphere/errors.py))
| Статус | `error_type` | Типичная причина |
|---|---|---|
| 400 | `invalid_argument` / `already_exists` | Некорректное тело, дублирующееся имя |
| 401 | `unauthenticated` | Отсутствующая/недействительная/истёкшая сессия |
| 403 | `unauthorized` | У сессии нет требуемой привилегии |
| 404 | `not_found` | Неизвестный параметр MOID/path |
| 409 | (зависит от обработчика) | Недопустимый переход состояния питания, конфликт блокировки |
| 501 | `error` | Достижимо только через fallback опционального legacy-стаба для необъявленных методов |
Все тела ошибок следуют форме vSphere Automation:
`{ "error_type": "...", "messages": [{ "default_message": "...", "id": "...", "args": [] }] }`.
## Задачи
Асинхронная работа (power, clone, snapshot, relocate, деплой OVF, guest
customize) возвращает id задачи. Опрашивайте:
```text
GET /api/cis/tasks/{task}
```
Строки задач фиксируются в `vsphere_tasks`; `progress` равен `100`, как
только `status` становится `SUCCEEDED`/`FAILED`. HTTP 200/201 на запросе
мутации означает «принято», а не «ВМ уже в конечном состоянии». См.
[Задачи](domains/tasks.md).
## Исследование
- Интерактивная документация FastAPI: `/docs`
- Инспектор методов в Web UI: `/` → каталог → метод
- Вспомогательные API UI: `/ui/api/catalog`, `/ui/api/method`,
`/ui/api/compatibility`
- Реестр покрытия: [`app/vsphere/rest/coverage.py`](../../app/vsphere/rest/coverage.py)
- Матрица уровней пути / каталога: [`app/vsphere/contracts/matrix.py`](../../app/vsphere/contracts/matrix.py)
## Эндпоинты совместимости
| Path | Формат |
|---|---|
| `/ui/api/compatibility?major=N` | JSON |
См. [Совместимость](compatibility.md) и [Покрытие API](api-coverage.md) для
полной разбивки Broadcom-universe в сравнении с реализованным.
+77
View File
@@ -0,0 +1,77 @@
**Language / Язык:** [English](../api-versions.md) | [Русский](api-versions.md)
# Версии API (vSphere catalog majors 69)
Web UI и evidence/compatibility отчёты просматривают четыре целочисленных **catalog
majors**, которые сопоставляются с label floors vSphere Automation API:
| Major | Метка vSphere | Строка версии contract |
|---|---|---|
| 6 | 7.0 | `7.0.0` |
| 7 | 7.0 U3 | `7.0.3` |
| 8 | 8.0 | `8.0.0` |
| 9 | 8.0 U2 (Automation 9.1 surface) | `8.0.2` |
Определения находятся в [`app/vsphere/contracts/matrix.py`](../../app/vsphere/contracts/matrix.py)
(`VERSIONS`, `PATH_FLOOR`). Каждый зарегистрированный REST path имеет **floor**
наименьший major, при котором он появляется в catalog — из того же
модуля. Undated paths по умолчанию получают наивысший major (9), пока не catalogued.
## Runtime vs catalog
Это самое важное различие в проекте:
- **Catalog major** — управляет тем, что показывает Web UI endpoint tree, `/ui/api/catalog`,
и compatibility/evidence отчёты для данного major.
- **Runtime surface** — симулятор всегда обслуживает **полную зарегистрированную
route table** с deep handlers или DB-backed stubs, независимо от
активного catalog major. Известный path никогда не возвращается как HTTP 501 из-за
version floor.
Hot-swap catalog major — это **documentation/browse**
переключатель, а не compatibility gate для live traffic. См.
[`available_for_request()`](../../app/vsphere/contracts/matrix.py) для точной
политики.
## Cold start
`GET /api/appliance/system/version` сообщает version string текущего
выбранного runtime source (по умолчанию `8.0.2` / major 9, если процесс не
переопределяет `app.state.runtime_source_version`).
## Hot-swap (catalog browse)
Просматривайте любой major в Web UI catalog или вызывайте:
```http
POST /ui/api/contract/apply?major=7
```
Эффекты:
- Web UI catalog, `/ui/api/compatibility` и evidence отчёты переключаются на
floor major 7 и ledger (`evidence/vsphere-7.0.3.json`).
- Изменение **process-local** и **не сохраняется**; restart возвращает
default (major 9).
- Зарегистрированные REST/SOAP routes продолжают отвечать своими реальными
handlers независимо от применённого major.
### Рекомендации для клиентов
- Большинству клиентов (pyvmomi, govmomi, Terraform, Pulumi, Ansible `uri`) не
нужно pin'ить catalog major — runtime surface не меняет форму
на его основе.
- Используйте catalog majors, когда нужно, чтобы Web UI / evidence view
отражали более старую метку vSphere для документации или скриншотов.
- После apply перепроверьте `/ui/api/compatibility?major=N` для активного
catalog state.
## Регенерация catalog artifacts
```bash
make vsphere-bundles # stub OpenAPI matrices + evidence ledgers
make vsphere-universe # regenerate universe.json from the Broadcom operations index
make evidence # regenerate per-major verified surface evidence ledgers
```
См. [Поверхность API](api-surface.md) и [Совместимость](compatibility.md).
+77
View File
@@ -0,0 +1,77 @@
**Language / Язык:** [English](../architecture.md) | [Русский](architecture.md)
# Архитектура
## Цели
`vmware-api-simulator` — stateful лабораторный эмулятор vSphere (Automation REST +
VIM SOAP). Главная цель дизайна — **практическая совместимость клиентов**:
сессии, inventory, жизненный цикл VM, обходы PropertyCollector, задачи,
stubs tagging/content library и роли AuthZ реализованы поверх большого
синтетического datastore, чтобы инструменты вроде curl, govc-подобных
потоков, pyvmomi и Terraform могли прогонять типовые пути без реального
vCenter.
Catalog majors **69** соответствуют floors vSphere 7.0 / 7.0U3 / 8.0 / 8.0U2.
Hot-swap меняет каталог только для browse/evidence в Web UI — он **не**
гейтит живые маршруты. Опциональный stub Proxmox `/api2/*` остаётся за
`ENABLE_PVE_STUB` (по умолчанию выключен).
## Контекст системы
```mermaid
flowchart LR
Client["API clients<br/>pyvmomi / Terraform / govc / REST SDKs"]
Admin["Lab operator"]
UI["Web lab UI"]
API["FastAPI application"]
Gateway["HTTPS gateway :443"]
Contract["vSphere contract matrix"]
Domain["vsphere domain + inventory"]
DB[(PostgreSQL)]
Obs["Logs / Prometheus / OpenTelemetry"]
Client -->|"/api /rest /sdk"| Gateway
Gateway --> API
UI --> Gateway
Admin -->|"seed / migrate"| API
API --> Contract
API --> Domain
Domain --> DB
API --> Obs
```
## Плоскости
| Плоскость | Путь | Заметки |
|---|---|---|
| Automation REST | `/api`, `/rest` | Заголовок сессии `vmware-api-session-id` |
| VIM SOAP | `/sdk` | Подмножество PropertyCollector + VM tasks |
| Lab UI helpers | `/ui/api/*` | Каталог, demo seed, совместимость |
| Опциональный PVE stub | `/api2/*` | Выкл., пока `ENABLE_PVE_STUB=true` |
## Модель данных
Inventory живёт в `vsphere_objects` (MOID, типы, props JSON, parent-ссылки).
Sessions, credentials, tasks, tags, libraries, snapshots и permissions —
соседние таблицы (миграции `009_vsphere.sql`, `010_vsphere_platform.sql`).
DB-backed Automation stubs используют `vsphere_api_state` (`011`); сессии
transfer content library и строки HttpNfcLease — в `vsphere_transfer_sessions` /
`vsphere_nfc_leases` (`012`); views/tokens PropertyCollector и console tickets —
в `vsphere_pc_state` / `vsphere_console_tickets` (`013`).
Профили seed (`small` / `large` / `demo-cluster`) строят детерминированный
кластер — по умолчанию **large** это ~10 hosts / **1000 VMs**.
## AuthZ
Credentials отображаются в roles → privilege sets. Мутирующие обработчики
используют `require_privilege(...)`; пути чтения — `require_read`. SOAP Login
выдаёт cookie, совместимый с VIM-сессиями.
## Связанные документы
- [Покрытие API](api-coverage.md)
- [Аутентификация](authentication.md)
- [Web UI](web-ui.md)
- [Клиенты](clients.md)
+101
View File
@@ -0,0 +1,101 @@
**Language / Язык:** [English](../authentication.md) | [Русский](authentication.md)
# Аутентификация
Основная плоскость: **vSphere Automation REST** sessions (`vmware-api-session-id`).
SOAP `/sdk` использует собственные `Login`/`Logout` на VIM `SessionManager`. Опциональная
legacy Proxmox stub-плоскость (`ENABLE_PVE_STUB=true`) сохраняет историческое поведение
`/api2/json/access/ticket` из общей platform lineage — это не default lab path и далее
не рассматривается.
## Session login (REST)
```http
POST /api/session
Authorization: Basic base64(user:password)
```
Успешный ответ:
- Body: JSON string session id (например, `"a1b2c3…"`)
- Header: `vmware-api-session-id: <id>`
- Cookie: `vmware-api-session-id=<id>` (`SameSite=Strict`, TTL 2 часа)
Legacy wrapper (те же credentials, форма `{ "value": "<session-id>" }`):
```http
POST /rest/com/vmware/cis/session
Authorization: Basic base64(user:password)
```
### Вызов API
```bash
SID=$(curl -sk -u 'administrator@vsphere.local:VMware1!' \
-X POST 'https://localhost/api/session' | tr -d '"')
curl -sk -H "vmware-api-session-id: $SID" \
'https://localhost/api/vcenter/vm'
```
Cookie-only клиенты также работают после login (`credentials: include` в
браузерном Web UI).
### Inspect / logout сессии
| Метод | Путь | Заметки |
|---|---|---|
| GET | `/api/session` | HTTP 200 с заголовками `x-vmware-session-user` / `x-vmware-session-roles` |
| DELETE | `/api/session` | Инвалидирует сессию и очищает cookie |
| GET / DELETE | `/rest/com/vmware/cis/session` | Legacy эквиваленты `{ "value": … }` |
Сессии хранятся в PostgreSQL (`vsphere_sessions`) с 2-часовым sliding
expiry — каждый аутентифицированный запрос продлевает `expires_at`. Истёкшие сессии
возвращают HTTP 401 при следующем lookup и лениво удаляются.
## Засеянные lab principals
Пароль для всех: `VMware1!`
| Principal | Роль |
|---|---|
| `administrator@vsphere.local` | Administrator |
| `readonly@vsphere.local` | ReadOnly |
| `operator@vsphere.local` | VirtualMachinePowerUser |
| `vmadmin@vsphere.local` | VirtualMachineAdministrator |
Credentials хранятся в `vsphere_credentials` (scrypt-hashed passwords,
массив `roles`) и идемпотентно re-insert'ятся при первом вызове `/api/session`
и каждым seed profile. См. [Authorization](domains/authz.md) для модели
привилегий и [Профили seed](seed-profiles.md) для соответствия четырёх
principals inventory-scoped permissions.
Mutating endpoints проверяют привилегии через `require_privilege(...)`; вызов
mutate path как `readonly@vsphere.local` возвращает **403**.
## SOAP `/sdk`
```xml
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:vim25">
<soapenv:Body>
<urn:Login>
<urn:_this type="SessionManager">SessionManager</urn:_this>
<urn:userName>administrator@vsphere.local</urn:userName>
<urn:password>VMware1!</urn:password>
</urn:Login>
</soapenv:Body>
</soapenv:Envelope>
```
`Login` выдаёт тот же underlying session id, возвращаемый как
`vmware-api-session-id` и как cookie `vmware_soap_session`; последующие SOAP
вызовы (pyvmomi, govmomi, Terraform provider `hashicorp/vsphere`, Pulumi)
передают этот cookie автоматически. `Logout` удаляет сессию. См.
[SOAP / VIM](domains/soap.md).
## Опциональная legacy Proxmox stub
Только при `ENABLE_PVE_STUB=true`: ticket login на `/api2/json/access/ticket`
с `PVEAuthCookie` + CSRF, унаследованный от общей simulator platform, от которой
этот проект fork'нулся. По умолчанию выключен (`ENABLE_PVE_STUB=false`) и
не используется vSphere docs, examples или test suites в этом репозитории.
+88
View File
@@ -0,0 +1,88 @@
**Language / Язык:** [English](../clients.md) | [Русский](clients.md)
# Клиенты
Используйте симулятор из распространённых стеков автоматизации VMware:
Python, Ansible, Terraform, Pulumi.
## Матрица подключений
| Стек | Транспорт | Примечания | Код |
|---|---|---|---|
| REST (curl / SDK) | HTTPS `:443` | `vmware-api-session-id` после Basic-сессии | `examples/python/vsphere_rest_smoke.py`, `vsphere_lifecycle.py` |
| SOAP / VIM | HTTPS `:443/sdk` | провайдеры pyvmomi / govmomi / Terraform / Pulumi | `examples/python/vsphere_soap_smoke.py` |
| Legacy `/rest` | HTTPS `:443` | обёртки `{ "value": … }` | `/rest/vcenter/vm` |
| Terraform | HTTPS `:443` | источники данных `hashicorp/vsphere` + опциональный ресурс ВМ | `examples/terraform/vsphere/` |
| Ansible | HTTPS `:443` | playbook жизненного цикла REST (модуль `uri`) | `examples/ansible/vsphere_playbook.yml` |
| Pulumi | HTTPS `:443` | кулинарная книга REST ComponentResource | `examples/pulumi/` |
| govc | HTTPS `:443` | `GOVC_URL=https://…` insecure | см. ниже |
| Go / Java / Perl | HTTPS `:443` | минимальные кулинарные книги REST (сессия по Basic-auth) | `examples/go/`, `examples/java/`, `examples/perl/` |
## Учётные данные (seed)
| Пользователь | Пароль | Роль |
|---|---|---|
| `administrator@vsphere.local` | `VMware1!` | Administrator |
| `readonly@vsphere.local` | `VMware1!` | ReadOnly |
| `operator@vsphere.local` | `VMware1!` | VirtualMachinePowerUser |
| `vmadmin@vsphere.local` | `VMware1!` | VirtualMachineAdministrator |
## Seed инвентаря
```bash
make seed # large: 10 хостов / 1000 ВМ
VSPHERE_PROFILE=demo-cluster make seed
VSPHERE_PROFILE=small make seed
```
## Быстрые кулинарные книги
```bash
# Все четыре стека (в стиле Python/Ansible/Terraform/Pulumi) внутри Compose
make client-cookbooks
# Python REST + SOAP CreateVM / NFC
VSPHERE_BASE=https://localhost python examples/python/vsphere_lifecycle.py
# Ansible
ansible-playbook -i examples/ansible/inventory.ini examples/ansible/vsphere_playbook.yml
# Terraform — источники данных hashicorp/vsphere (plan) + опциональный ресурс CreateVM
cd examples/terraform/vsphere
terraform init
TF_VAR_vsphere_server=localhost TF_VAR_create_lab_vm=false terraform plan
TF_VAR_vsphere_server=localhost TF_VAR_create_lab_vm=true terraform apply
# Pulumi REST
cd examples/pulumi && pulumi up
```
Проверено против gateway (`:443`): жизненный цикл Python, playbook Ansible,
REST в стиле Pulumi и `terraform plan` (источники данных
datacenter/cluster/datastore/network/VM) — всё зелёное. SOAP
`CreateVM_Task` доступен для пути ресурса; используйте свежий seed, если
имена папок были переименованы зондами (`make seed`).
## govc (опциональный инструмент на хосте)
```bash
export GOVC_URL=https://localhost
export GOVC_USERNAME=administrator@vsphere.local
export GOVC_PASSWORD='VMware1!'
export GOVC_INSECURE=1
govc about
govc ls /
govc find / -type m | head
govc vm.info web-01
```
## Smoke-тест pyvmomi
```bash
docker compose run --rm --no-deps -e VSPHERE_BASE=http://simulator:8080 \
-e TEST_DATABASE_URL=postgresql://vmware:vmware@postgres:5432/vmware_simulator \
dev pytest tests/compatibility/test_vsphere_pyvmomi.py -q
```
Руководства по языкам: [examples/overview.md](examples/overview.md). Покрытие:
[api-coverage.md](api-coverage.md).
+87
View File
@@ -0,0 +1,87 @@
**Language / Язык:** [English](../compatibility-0.1.0.md) | [Русский](compatibility-0.1.0.md)
# Отчёт совместимости — 0.1.0
Этот отчёт фиксирует evidence для релиза симулятора 0.1.0 относительно реестра
маршрутов vSphere Automation API (catalog majors 69, основной contract major 9 /
8.0 U2). Это матрица ограничений по измерениям *качества / внешней интеграции*,
а не утверждение общей аппаратной совместимости с vCenter/ESXi.
Пользовательский обзор — [compatibility.md](compatibility.md). Живые
машиночитаемые счётчики всегда доступны из
`/ui/api/compatibility?major=N`, когда симулятор запущен.
## Сводка (major 9 / основной контракт vSphere 8.0 U2)
| Уровень | Methods | Доля universe | Evidence |
|---|---:|---:|---|
| Declared in universe (Broadcom operations index → route table) | 1077 | 100% | `app/vsphere/rest/universe.json` |
| Implemented at major 9 (catalog floor) | **1077** | **100%** | `app/vsphere/contracts/matrix.py` |
| Core deep handlers (inventory/lifecycle/tagging/content/appliance) | 104 | 9.7% | `app/vsphere/rest/coverage.py` (`CORE_IMPLEMENTED`) |
| DB-backed stub surface (остальной реестр) | ~973 | 90.3% | `app/vsphere/rest/stub_surface.py` против `vsphere_api_state` |
| Verified / observed surface ledger | **1077** | **100%** | `evidence/vsphere-8.0.2.json` |
## Покрытие по catalog major
| Major | Метка vSphere | Implemented | Universe | Coverage |
|---|---|---:|---:|---:|
| 6 | 7.0 | 31 | 1077 | 2.88% |
| 7 | 7.0 U3 | 77 | 1077 | 7.15% |
| 8 | 8.0 | 103 | 1077 | 9.56% |
| 9 | 8.0 U2 | 1077 | 1077 | 100.00% |
**Implemented** здесь — оценка catalog-floor для browse в Web UI и
evidence-отчётов, перегенерируется через `make evidence` / `make vsphere-bundles`
и защищена `tests/compatibility/test_verified_surface.py`. Она **не**
гейтит живой трафик — почему runtime всегда обслуживает зарегистрированный
маршрут независимо от применённого major, см. [Поверхность API](api-surface.md).
## Реализованная поверхность (верхний уровень)
- **Session**: `/api/session`, `/rest/com/vmware/cis/session`, SOAP
`Login`/`Logout` — всё устойчиво в PostgreSQL (`vsphere_sessions`,
`vsphere_credentials`).
- **Inventory**: list+get для VM/host/datastore/network/datacenter/cluster/folder/resource-pool,
плюс create/delete для datacenter/cluster/folder/resource-pool.
- **VM lifecycle**: create, delete, power, hardware (CPU/memory/disk/NIC/boot),
snapshots, clone, relocate, guest identity/networking/power/customization,
console tickets, tools.
- **Tasks**: `/api/cis/tasks`, реальные ids из `vsphere_tasks`, SOAP task MoRefs.
- **Tagging / content library**: categories, tags, associations, libraries,
library items, update/download sessions, OVF deploy.
- **Authorization**: privileges, roles, permissions CRUD, identity providers.
- **Appliance**: version, health, networking (hostname/DNS), timesync.
- **SOAP / VIM**: RetrieveServiceContent, PropertyCollector
(RetrieveProperties/Ex, ContinueRetrievePropertiesEx, CreateFilter,
WaitForUpdatesEx), FindBy* / FindChild, CreateVM_Task и связанные, guest
file operations, HttpNfcLease import flow, WSDL stub.
- **Platform lab surfaces**: seeded (не бинарно совместимые) stand-in'ы
NSX/Supervisor/vSAN/SAML-OIDC/VECS-cert — точный список и оговорки в
[Покрытие API](api-coverage.md).
## Принцип персистентности
Каждый путь create/update/delete пишет в PostgreSQL (таблицы и/или catch-all
`vsphere_api_state`). Секреты могут храниться, но не должны отдаваться на GET.
Пользовательские ошибки «not supported in the emulator» для зарегистрированных
путей запрещены — см. `.cursor/rules/durable-simulator.mdc`.
## Известные ограничения
| Область | Текущее поведение |
|---|---|
| Внешние системы | NSX/LDAP/SAML/OIDC/ACME не обращаются к реальным remotes; состояние симулируется локально |
| TLS | Локальный nginx gateway только с закоммиченным self-signed development key |
| Сертификация клиентов | SOAP smoke в стиле pyvmomi/govmomi + cookbook'и Ansible/Terraform/Pulumi; не формальный certification suite для каждой версии провайдера |
| Smoke провайдера | Набор `pulumi-vsphere` в `pulumi-tests/` (`make pulumi-tests`) гоняет SOAP inventory/VM/tag с проверкой непустых export'ов; семантическая глубина по-прежнему разная (deep handlers vs DB-backed stubs) |
Полное покрытие реестра на major 9 означает, что HTTP 501 «handler pending»
не должен появляться ни для одного маршрута в реестре симулятора. *Качество*
совместимости (точный паритет крайних случаев vSphere) по-прежнему углубляется
тестами и observation.
При импорте обновлённого дампа Broadcom operations index: перегенерируйте
`universe.json` (`make vsphere-universe`), bundles/evidence
(`make vsphere-bundles`, `make evidence`), запустите
`pytest tests/compatibility/test_verified_surface.py` и закоммитьте обновлённые
ledgers `evidence/vsphere-*.json`.
+79
View File
@@ -0,0 +1,79 @@
**Language / Язык:** [English](../compatibility.md) | [Русский](compatibility.md)
# Совместимость
Этот документ объясняет, как симулятор заявляет совместимость с vSphere
Automation API по мажорам каталога **69**. Когда процесс запущен,
предпочитайте живые отчёты.
## Живые отчёты
| URL | Формат |
|---|---|
| `/ui/api/compatibility?major=N` | JSON |
Web UI также предоставляет панель совместимости, управляемую этим
endpoint'ом.
## Покрытие реестра в сравнении с проверенной поверхностью
| Мажор | Метка vSphere | Реализовано / universe | Покрытие |
|---|---|---:|---:|
| 6 | 7.0 | 31 / 1077 | 2.9% |
| 7 | 7.0 U3 | 77 / 1077 | 7.2% |
| 8 | 8.0 | 103 / 1077 | 9.6% |
| 9 | 8.0 U2 (поверхность Automation 9.1) | **1077 / 1077** | **100%** |
- **Universe** — уникальные маршруты verb+path, полученные из публичного
[индекса операций vSphere Automation API](https://developer.broadcom.com/xapis/vsphere-automation-api/latest/operation-index/)
(1348 документированных операций → ~1037 уникальных маршрутов → 1077
зарегистрированных в таблице маршрутов этого симулятора, поскольку
некоторые пути обслуживают несколько именованных операций).
- **Реализовано (по мажору)** — маршруты, чей уровень каталога
(`app/vsphere/contracts/matrix.py`) равен этому мажору или ниже. Это
оценка **каталога/документации**, а не ограничение живого трафика.
- **Runtime** — независимо от применённого мажора каталога, каждый
зарегистрированный маршрут всегда обслуживается своим реальным
обработчиком (104 глубоких обработчика) или DB-backed поверхностью
стабов. См. [Поверхность API](api-surface.md).
После **Apply as runtime** (`POST /ui/api/contract/apply?major=N`) живой
отчёт загружает журнал этого мажора (`evidence/vsphere-{version}.json`), так
что панель совместимости Web UI отражает выбранный мажор.
## Измерения evidence
Журналы по мажорам в `evidence/vsphere-{version}.json` записывают счётчики
`declared`, `implemented`, `observed` и `verified`, а также разбивки по
HTTP-методам и доменам (`auth_session`, `inventory`, …). Регенерируйте с
помощью:
```bash
make evidence # app/evidence_gen.py
make vsphere-bundles # стаб-бандлы OpenAPI + журналы evidence вместе
```
Исполняемое подтверждение этих заявлений:
| Набор тестов | Роль |
|---|---|
| `tests/compatibility/test_verified_surface.py` | hot-swap + дрейф журнала + пороги оценки |
| `tests/compatibility/test_group_smoke.py` | представительные мутации групп REST с PostgreSQL |
| `tests/compatibility/test_vsphere_pyvmomi.py` | внешний smoke-тест SOAP через pyvmomi |
| `tests/integration/test_vsphere_full_api.py` | широкое интеграционное покрытие REST/SOAP |
Дополнительные cookbook'и под [`examples/`](../../examples/README.ru.md)
и lab-набор `pulumi-vsphere` под
[`pulumi-tests/`](../../pulumi-tests/README.ru.md) (`make pulumi-tests`)
выполняются вручную или опционально в CI.
## Известные поведенческие ограничения
| Область | Поведение |
|---|---|
| Внешние системы | NSX Manager, живые LDAP/SAML/OIDC IdP и ACME-директории не обращаются к реальным удалённым сервисам; только seeded/локальное состояние |
| TLS | Только локальный self-signed development-gateway (Compose); используйте свои сертификаты / cert-manager для реальных развёртываний |
| Гипервизор | Нет реального выполнения ESXi/KVM; нет бинарных загрузок NFC |
| Корпус наблюдений | Санированные данные наблюдений реального vCenter остаются ограниченными; глубокий семантический паритет проверяется путь-за-путём указанными выше наборами тестов, а не исчерпывающим сравнением с production |
Исторические заметки о релизах: [compatibility-0.1.0.md](compatibility-0.1.0.md).
+96
View File
@@ -0,0 +1,96 @@
**Language / Язык:** [English](../configuration.md) | [Русский](configuration.md)
# Конфигурация
Настройки приложения загружаются из окружения (см. `.env.example`).
Docker Compose инжектирует многие из них для сервиса `simulator`; значения,
объявленные в `environment:` в `docker-compose.yml`, переопределяют `.env` для этого
сервиса. Типизированная модель настроек находится в [`app/config.py`](../../app/config.py).
## Основное
| Переменная | По умолчанию / пример | Значение |
|---|---|---|
| `APP_HOST` | `0.0.0.0` | Адрес bind |
| `APP_PORT` | `8080` | Внутренний порт uvicorn (не публикуется; gateway публикует vCenter HTTPS) |
| `DATABASE_URL` | `postgresql://vmware:vmware@postgres:5432/vmware_simulator` | asyncpg DSN |
| `DB_POOL_MIN_SIZE` | `1` | Минимум пула |
| `DB_POOL_MAX_SIZE` | `10` | Максимум пула |
| `DB_CONNECT_TIMEOUT_SECONDS` | `10` | Таймаут подключения |
| `DB_COMMAND_TIMEOUT_SECONDS` | `30` | Таймаут команды |
| `LOG_LEVEL` | `INFO` | Уровень логирования |
| `REQUEST_ID_HEADER` | `X-Request-ID` | Заголовок корреляции запросов |
## vSphere seed inventory
| Переменная | По умолчанию | Значение |
|---|---|---|
| `SEED_VSPHERE_PROFILE` | `large` | `small` \| `large` \| `demo-cluster` — см. [Профили seed](seed-profiles.md) |
| `SEED_VSPHERE_LARGE_HOSTS` | `10` | Число хостов для профиля `large` |
| `SEED_VSPHERE_LARGE_VMS` | `1000` | Число VM для профиля `large` |
## Опциональная legacy-плоскость
| Переменная | По умолчанию | Значение |
|---|---|---|
| `ENABLE_PVE_STUB` | `false` | Включает legacy Proxmox VE `/api2/*` stub-плоскость, унаследованную из общей platform lineage. Нативная vSphere `/api` + `/rest` + `/sdk` — основная плоскость по умолчанию независимо от этого флага. |
## Contract и catalog
| Переменная | Значение |
|---|---|
| `CONTRACT_SNAPSHOT` | Опциональный путь к нормализованному PVE-style snapshot (актуально только при `ENABLE_PVE_STUB=true`) |
| `CONTRACT_FALLBACK` | `error` (default), `schema-default`, или `fixture` — fallback-поведение для опциональной stub-плоскости |
| `COMPATIBILITY_EVIDENCE` | Опциональный путь к evidence JSON для отчётов совместимости |
| `CATALOG_ARTIFACT_URL_6``_9` | Метки catalog majors vSphere (6→7.0, 7→7.0 U3, 8→8.0, 9→8.0 U2); stub URLs, не live downloads |
Runtime hot-swap (Web UI / `POST /ui/api/contract/apply?major=N`) переключает
активный **catalog** major, используемый Web UI и compatibility/evidence
отчётами. Он не ограничивает зарегистрированную REST/SOAP поверхность — каждый
известный маршрут всегда обслуживается реальным обработчиком или DB-backed stub.
См. [Версии API](api-versions.md).
## Безопасность и задачи
| Переменная | Значение |
|---|---|
| `TICKET_SIGNING_KEY` | HMAC signing key для сессий (**меняйте вне toy labs**) |
| `TASK_WORKER_CONCURRENCY` | Число leased asyncio workers (132) |
| `TASK_LEASE_SECONDS` | Длительность lease PostgreSQL-задачи |
| `SIMULATION_TIME_SCALE` | Ускоряет симулированные длительности задач (выше = быстрее) |
## Client test hooks
| Переменная | Значение |
|---|---|
| `TEST_DATABASE_URL` | DSN для integration-тестов |
| `VSPHERE_BASE` | Базовый URL для cookbooks/probes (`https://localhost` с хоста, `http://simulator:8080` изнутри Compose) |
## Порты и TLS
| Endpoint | Назначение |
|---|---|
| `https://localhost` | Основная vCenter HTTPS точка входа (curl, browsers, pyvmomi, govmomi, Terraform, большинство examples) |
| `http://localhost` | HTTP-грань для лабораторных нужд |
| `localhost:5434` | PostgreSQL (только localhost) |
| Internal `simulator:8080` | Прямой процесс FastAPI; доступен только внутри Compose network |
Вшитый сертификат в `docker/tls/` — одноразовый development material.
Никогда не используйте его вне локальных labs. См. [Безопасность](security.md) и
[Порты](ports.md).
## Заметки по Compose
- `migrate` выполняется один раз; `simulator` ждёт успешного migrate.
- Development Compose bind-mount'ит репозиторий и включает Uvicorn reload.
- Сервис `api-gateway` (nginx) публикует `443`/`80` и проксирует на
внутренний процесс `simulator:8080`; устанавливает `X-VMware-Service` /
`X-Forwarded-Port`, чтобы будущие routers могли определить использованный listener.
## Открытые и неиспользуемые example keys
`.env.example` всё ещё перечисляет несколько ключей из общей platform lineage, которые
**не** потребляются текущей vSphere-first моделью настроек, в частности
`SIMULATION_SEED`, `SIMULATOR_ADMIN_ENABLED` и `SIMULATOR_ADMIN_TOKEN`. Не
предполагайте, что аутентифицированный admin API `/_simulator` существует сегодня — см.
[Безопасность](security.md).
+43
View File
@@ -0,0 +1,43 @@
**Language / Язык:** [English](../../domains/README.md) | [Русский](README.md)
# Руководства по доменам
Эти страницы описывают устойчивую семантику по областям API. Для исчерпывающих
списков методов используйте каталог Web UI или OpenAPI (`/docs`), либо
непосредственно
[`app/vsphere/rest/coverage.py`](../../../app/vsphere/rest/coverage.py) —
runtime всегда обслуживает полную зарегистрированную поверхность независимо от
активного catalog major.
| Руководство | Темы |
|---|---|
| [Session](session.md) | `/api/session`, legacy `/rest` session, SOAP `Login`/`Logout` |
| [Inventory](inventory.md) | Datacenter, cluster, folder, resource pool, host, datastore, network CRUD |
| [Виртуальные машины](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 |
| [Авторизация](authz.md) | Roles, privileges, permissions |
## Карта персистентности
- Объекты inventory (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 → `vsphere_datastore_files`.
- Оставшиеся маршруты Broadcom Automation API (DB-backed stub surface) →
`vsphere_api_state` (миграция `011`).
- Update/download sessions content library → `vsphere_transfer_sessions`
(миграция `012`).
- Состояние transfer HttpNfcLease → `vsphere_nfc_leases` (миграция `012`).
- Views PropertyCollector / токены WaitForUpdates → `vsphere_pc_state`
(миграция `013`).
- Console tickets → `vsphere_console_tickets` (миграция `013`).
+35
View File
@@ -0,0 +1,35 @@
**Language / Язык:** [English](../../domains/appliance.md) | [Русский](appliance.md)
# Appliance
Поверхности vCenter Server Appliance (VCSA) — 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).
## Эндпоинты
| Метод | Путь | Заметки |
|---|---|---|
| GET | `/api/appliance/system/version` | Читается без сессии; отражает метку активного catalog major |
| GET | `/api/appliance/health/system` | Сводка общего health |
| GET/PUT/POST | `/api/appliance/networking` | Hostname, DNS, default gateway, interfaces, proxy |
| GET/PUT/POST | `/api/appliance/networking/dns/hostname` \| `/dns/servers` \| `/dns/domains` | Сфокусированные зеркала, синхронизированные с `/networking` |
| GET | `/api/appliance/timesync` | Режим NTP + servers |
| GET | `/api/vcenter/certificate-management/vcenter/tls[-csr]` \| `/trusted-root-chains` | Stand-in'ы machine-cert / CSR / trust-chain |
## Основные моменты
- Defaults моделируют реалистичный single-nic VCSA (`vcenter.lab.local`,
`192.168.1.50/24`, gateway `192.168.1.1`, DNS `8.8.8.8`/`1.1.1.1`).
- `save_networking` держит сфокусированные DNS-зеркала
(`/dns/hostname`, `/dns/servers`, `/dns/domains`) согласованными с полным
документом `/networking`, чтобы работали оба стиля клиентов Automation API.
- Состояние идемпотентно засевается один раз на свежую БД
(`seed_appliance_state`) и хранится в `vsphere_api_state`.
- Эндпоинты TLS/certificate-management — seeded stand-in'ы, не настоящее
хранилище сертификатов VECS — см. [Покрытие API](../api-coverage.md).
`/api/appliance/system/version` намеренно не требует сессию в этой lab-сборке
(поведение реального vCenter зависит от версии), чтобы smoke-скрипты могли
проверить доступность до аутентификации.
+51
View File
@@ -0,0 +1,51 @@
**Language / Язык:** [English](../../domains/authz.md) | [Русский](authz.md)
# Авторизация
Gate роль → privilege для мутирующих REST-эндпоинтов (и decorator-style hook
для SOAP): [`app/vsphere/security/authz.py`](../../../app/vsphere/security/authz.py),
[`platform_rest.py`](../../../app/vsphere/rest/platform_rest.py).
## Эндпоинты
| Метод | Путь | Заметки |
|---|---|---|
| GET | `/api/vcenter/privilege` | Каталог привилегий |
| GET | `/api/vcenter/authorization/roles` | Role → набор privilege |
| GET/POST/DELETE | `/api/vcenter/authorization/permissions[/{permission_id}]` | Привязки principal ↔ role ↔ entity |
| GET/POST/PATCH/DELETE | `/api/vcenter/identity/providers[/{provider}]` | Stand-in'ы identity-provider LocalOS + OIDC + SAML |
## Роли (seed)
| Роль | Область |
|---|---|
| `Administrator` | Каждая привилегия в каталоге |
| `ReadOnly` | `System.Anonymous`, `System.Read`, `System.View`, `Datastore.Browse` |
| `VirtualMachinePowerUser` | Read + взаимодействия power/snapshot/clone |
| `VirtualMachineAdministrator` | Набор power-user + привилегии create/delete/reconfigure/tag/content-library |
`ROLE_PRIVILEGES` в `authz.py` задаёт точные наборы привилегий; неполный
пример gated-привилегий: `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`.
## Как работает gating
- `require_privilege(*needed)` — фабрика зависимостей FastAPI: резолвит
сессию, загружает роли (из сессии или `vsphere_credentials`, если нет),
и поднимает HTTP 403 (`unauthorized`), если отсутствует любая из
перечисленных привилегий.
- `require_read` — сокращение для `require_privilege("System.Read")`.
- Permissions также могут ограничить роль конкретным entity MOID
(`PermissionSpec(principal, role, entity_moid, propagate)`); seed
ограничивает `readonly@vsphere.local` datacenter'ом, а двух VM-admin
принципалов — папкой VM.
## Seeded-принципалы
Четыре принципала `@vsphere.local` и их роли — в
[Аутентификация](../authentication.md); как permissions скоупятся по
профилю — в [Профили seed](../seed-profiles.md).
+38
View File
@@ -0,0 +1,38 @@
**Language / Язык:** [English](../../domains/content-library.md) | [Русский](content-library.md)
# Content library
Локальные content libraries, library items, upload/download sessions и 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).
## Эндпоинты
| Метод | Путь | Заметки |
|---|---|---|
| GET | `/api/content/library` | Список library ids |
| POST | `/api/content/local-library` | Создать local library |
| GET/POST | `/api/content/library/item` | Список / create items (`?library_id=`) |
| POST | `/api/vcenter/ovf/library-item/{item_id}` | Deploy OVF item → новая `VirtualMachine` + task |
| POST | `/api/content/library/item/update-session[/{session_id}[/file]]` | Поток push-upload (стиль Ansible/Terraform) |
| GET/POST | `/api/content/library/item/download-session[/{session_id}[/file]]` | Поток pull-download |
| GET/PUT/POST | `/nfc/{lease}` \| `/nfc/{lease}/files/{filename}` \| `/nfc/{lease}/complete` | Эндпоинты transfer в стиле HttpNfcLease для SOAP import path |
## Основные моменты
- Libraries/items живут в `vsphere_libraries` / `vsphere_library_items`;
seed создаёт две libraries («Local Content», «Published Templates») с
OVF-typed items (`ubuntu-22.04`, `centos-stream-9`, `golden-image`).
- Update/download sessions живут в PostgreSQL (`vsphere_transfer_sessions`,
миграция `012`) и моделируют handshake передачи файлов — не реальное
byte-for-byte хранилище OVF/VMDK. Строки HttpNfcLease — в `vsphere_nfc_leases`.
- `deploy_ovf_from_library` создаёт реальную строку `VirtualMachine` и
возвращает task id, зеркаля SOAP-поток `ImportVApp_Task` /
`CreateImportSpec` + `HttpNfcLease*`, используемый govc-style `ovf.import`.
- Для create нужны `ContentLibrary.CreateLocalLibrary` / `.AddLibraryItem`,
для deploy — `VirtualMachine.Provisioning.DeployTemplate`.
Операции HttpNfcLease progress/complete/abort для upload-heavy клиентов —
[SOAP / VIM](soap.md).
+46
View File
@@ -0,0 +1,46 @@
**Language / Язык:** [English](../../domains/inventory.md) | [Русский](inventory.md)
# Inventory
Listing + CRUD для datacenter, cluster, folder, resource pool, host и
datastore/network:
[`app/vsphere/rest/router.py`](../../../app/vsphere/rest/router.py),
[`app/vsphere/domain/inventory_ops.py`](../../../app/vsphere/domain/inventory_ops.py).
## Эндпоинты
| Метод | Путь | Заметки |
|---|---|---|
| GET | `/api/vcenter/datacenter` | Список |
| POST/DELETE | `/api/vcenter/datacenter[/{datacenter}]` | Create засевает подпапки host/vm/datastore/network |
| GET | `/api/vcenter/cluster` | Список |
| POST/DELETE | `/api/vcenter/cluster[/{cluster}]` | Create засевает `ResourcePool` |
| GET | `/api/vcenter/folder` | Список; `GET /api/vcenter/folder/{folder}/children` |
| POST/DELETE | `/api/vcenter/folder[/{folder}]` | |
| GET | `/api/vcenter/resource-pool` | Список |
| 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` | Переключение maintenance mode |
| GET | `/api/vcenter/datastore[/{datastore}]` | Type, capacity, free space, accessibility |
| GET | `/api/vcenter/network` | Standard networks + distributed portgroups |
Legacy `/rest/vcenter/*` зеркалит большинство GET-путей с конвертом
`{ "value": … }` — см. [Поверхность API](../api-surface.md).
## Основные моменты
- Каждый объект inventory — строка в `vsphere_objects` (MOID, type, name,
`parent_moid`, `props` JSONB) — см.
[`app/vsphere/inventory.py`](../../../app/vsphere/inventory.py).
- Конвенции MOID следуют формам реального vCenter: `datacenter-NN`,
`domain-cNN` (cluster), `resgroup-NN` (resource pool), `group-vNN`/`group-hNN`/
`group-sNN`/`group-nNN` (папки VM/host/datastore/network), `host-NN`,
`datastore-NN`, `network-NN` / `dvportgroup-NN`.
- `list_hosts`/`list_clusters`/и т.п. фильтруют живое состояние PostgreSQL;
отдельного кэша для инвалидации после мутации нет.
- Список VM (`GET /api/vcenter/vm`) поддерживает фильтры: `names`,
`power_states`, `hosts`, `folders`, `datacenters`, `clusters`,
`resource_pools`, плюс пагинацию `limit`/`cursor`.
Форма топологии по умолчанию — [Профили seed](../seed-profiles.md);
операции по VM — [Виртуальные машины](vm.md).
+35
View File
@@ -0,0 +1,35 @@
**Language / Язык:** [English](../../domains/networking.md) | [Русский](networking.md)
# Networking
Standard networks, distributed portgroups/switches и host networking:
[`app/vsphere/rest/router.py`](../../../app/vsphere/rest/router.py),
[`platform_rest.py`](../../../app/vsphere/rest/platform_rest.py).
## Эндпоинты
| Метод | Путь | Заметки |
|---|---|---|
| GET | `/api/vcenter/network` | Объекты standard `Network` + `DistributedVirtualPortgroup` |
| GET/POST | `/api/vcenter/network/dvs` | Distributed virtual switches |
| POST | `/api/vcenter/network/dvpg` | Создать distributed portgroup |
| GET | `/api/vcenter/host/{host}/networking` | DNS, default gateway, интерфейс `vmk0`, routing |
| GET/PUT/POST | `/api/appliance/networking` \| `/networking/dns/{hostname,servers,domains}` | Networking на уровне appliance vCenter (см. [Appliance](appliance.md)) |
Legacy `GET /rest/vcenter/network` зеркалит список.
## Основные моменты
- `nics[].value.backing` каждой VM указывает либо на `STANDARD_PORTGROUP`
(`network-41`, «VM Network»), либо на `DISTRIBUTED_PORTGROUP`
(`dvportgroup-4N`, с `vlan_id`).
- Топология по умолчанию засевает один `VmwareDistributedVirtualSwitch`
(`dvs-51`, `mtu: 9000`) и 1–3 дополнительных distributed portgroup в
зависимости от размера профиля.
- Host networking (`GET /api/vcenter/host/{host}/networking`) возвращает DNS
servers/domains, default gateway и один management-интерфейс `vmk0` с
детерминированным IPv4 по индексу host.
- Пути Automation API с меткой NSX (tier-0 gateway, projects, edges,
VPC/subnets) — seeded lab stand-in'ы под `namespace-management` — см.
таблицу «Platform surfaces» в [Покрытие API](../api-coverage.md); это не
реальный NSX Manager.
+32
View File
@@ -0,0 +1,32 @@
**Language / Язык:** [English](../../domains/session.md) | [Русский](session.md)
# Session
Устойчивая идентичность сессии, общая для REST и SOAP:
[`app/vsphere/security/session.py`](../../../app/vsphere/security/session.py).
## Эндпоинты
| Метод | Путь | Заметки |
|---|---|---|
| POST | `/api/session` | Basic auth → JSON-строка session id + заголовок/cookie `vmware-api-session-id` |
| GET | `/api/session` | HTTP 200; заголовки `x-vmware-session-user` / `x-vmware-session-roles` |
| DELETE | `/api/session` | Инвалидирует сессию, очищает cookie |
| POST/GET/DELETE | `/rest/com/vmware/cis/session` | Legacy-эквиваленты `{ "value": … }` |
| POST | SOAP `SessionManager.Login` | Возвращает тот же session id; ставит cookie `vmware_soap_session` |
| POST | SOAP `SessionManager.Logout` | Удаляет сессию |
## Основные моменты
- Сессии — непрозрачные 32-символьные hex-токены в `vsphere_sessions` со
**скользящим TTL 2 часа** — каждый аутентифицированный вызов продлевает
`expires_at`.
- Четыре лабораторные учётки (`vsphere_credentials`, scrypt-хеш) идемпотентно
обеспечиваются при первом login и каждым профилем seed
(`ensure_default_credentials`).
- `require_session` резолвит сессию из заголовка или cookie
`vmware-api-session-id`; отсутствует/истекла → HTTP 401.
- Роли привязываются к сессии при lookup (`vsphere_credentials.roles`) и
управляют [Авторизацией](authz.md).
Полные примеры запросов — [Аутентификация](../authentication.md).
+68
View File
@@ -0,0 +1,68 @@
**Language / Язык:** [English](../../domains/soap.md) | [Русский](soap.md)
# SOAP / VIM
Минимальный VIM SDK для клиентов в стиле pyvmomi / govmomi (провайдер
Terraform `hashicorp/vsphere`, 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).
## Эндпоинт
Все операции POST'ят SOAP-конверт на `/sdk` (также `/sdk/`). Вспомогательные
маршруты:
| Метод | Путь | Заметки |
|---|---|---|
| GET | `/sdk/vimService.wsdl` (alias `/sdk/vim.wsdl`) | WSDL stub со списком реализованных операций |
| GET | `/sdk/about.do` (alias `/about.do`) | Человекочитаемая страница «VMware vCenter Server» |
| POST | `/sdk/vim25/{version}/SessionManager/SessionManager/Login` | Login-вариант с JSON-телом, используемый некоторыми SDK |
## Реализованные операции
- `RetrieveServiceContent`, `Login`, `Logout`
- `RetrieveProperties`, `RetrievePropertiesEx`, **ContinueRetrievePropertiesEx**
(токены пагинации; plural `<objects>`), `CreateFilter`,
`WaitForUpdatesEx` (version tokens; пустые polls), `CreateContainerView`,
`DestroyPropertyFilter`
- `FindByInventoryPath` (пути без корневой папки `Datacenters`, как в
конвенциях govmomi), `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` (в паре с REST `/nfc/{lease}`
см. [Content library](content-library.md))
- `QueryConfigOption`, `QueryConfigOptionEx`, `QueryConfigOptionDescriptor`,
`QueryConfigTarget`
- Stub PBM (`/pbm`) для клиентов, учитывающих storage policy
## Основные моменты
- `Login` выдаёт ту же underlying-сессию, что и REST (`vmware-api-session-id`
cookie/header плюс cookie `vmware_soap_session`) — см.
[Session](session.md).
- `VIM_VERSION` зафиксирован как `8.0.2` с ≤3 компонентами через точку, так
как `hashicorp/vsphere` строго парсит `AboutInfo.version`.
- Type-strict MOR lookup отклоняет ссылку `VirtualApp:resgroup-*`,
резолвящуюся как plain `ResourcePool` — важно для Terraform resource path
`CreateVM_Task`.
- Операции, возвращающие задачу, создают реальную строку в `vsphere_tasks`
(общую с REST — см. [Tasks](tasks.md)), включая MoRefs `info.result` при
create/clone.
- Filters PropertyCollector, ContainerViews и version tokens WaitForUpdatesEx
живут в `vsphere_pc_state` (миграция `013`) между перезапусками процесса
в рамках лаборатории.
- `Folder.childType` отдаётся как `ArrayOfString`; строковые свойства несут
`xsi:type="xsd:string"`, чтобы их принимал decoder govmomi; `Datastore.host`
`ArrayOfDatastoreHostMount`; у `Cluster`/`Host` есть `environmentBrowser`.
Примеры подключений pyvmomi/govmomi/Terraform/Pulumi — [Клиенты](../clients.md);
минимальный raw-XML smoke —
[examples/python/vsphere_soap_smoke.py](../../../examples/python/vsphere_soap_smoke.py).
+37
View File
@@ -0,0 +1,37 @@
**Language / Язык:** [English](../../domains/storage.md) | [Русский](storage.md)
# Storage
Datastores, метаданные файлов datastore, устройства хранения host и 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).
## Эндпоинты
| Метод | Путь | Заметки |
|---|---|---|
| GET | `/api/vcenter/datastore[/{datastore}]` | Type (`VMFS`/`NFS`), capacity, free space, `multiple_host_access` |
| GET/POST | `/api/vcenter/datastore/{datastore}/files` | Список / регистрация метаданных файлов (пути ISO, VMX, VMDK) |
| GET | `/api/vcenter/host/{host}/storage/storage-device` | Seeded local disk devices (`naa.*`, capacity, флаг SSD) |
| GET | `/api/vcenter/storage/policies[/{policy}/vm]` | Storage-based policy management, в т.ч. lab-политики `policy_type: VSAN` |
Legacy `GET /rest/vcenter/datastore` зеркалит список в конверте
`{ "value": … }`.
## Основные моменты
- Строки datastore засеваются реалистичными парами capacity/free-space
(`type`, `capacity`, `free_space`, `accessible`,
`multiple_host_access`) — см.
[`app/vsphere/profiles.py`](../../../app/vsphere/profiles.py).
- Метаданные файлов живут в `vsphere_datastore_files` (`path`, `size`, `type`);
seed заранее заполняет ISO и записи `.vmx`/`.vmdk` VM
(`seed_platform_extras`).
- Среди storage policies есть lab-политика с меткой vSAN `RAID1` — оговорку
по vSAN (seeded lab data, не реальный кластер vSAN) см. в таблице
«Platform surfaces» в [Покрытие API](../api-coverage.md).
- Устройства хранения host — синтетические диски на host, не реальные extents
ESXi VMFS; флаги capacity/SSD детерминированно зависят от индекса host.
+33
View File
@@ -0,0 +1,33 @@
**Language / Язык:** [English](../../domains/tagging.md) | [Русский](tagging.md)
# Tagging
Сервис CIS tagging (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).
## Эндпоинты
| Метод | Путь | Заметки |
|---|---|---|
| GET/POST | `/api/cis/tagging/category` | Список / create (`cardinality`, `associable_types`) |
| GET/DELETE | `/api/cis/tagging/category/{category_id}` | |
| GET/POST | `/api/cis/tagging/tag` | Список / create под category |
| GET/DELETE | `/api/cis/tagging/tag/{tag_id}` | |
| POST | `/api/cis/tagging/tag-association` | Attach/detach тега к/от объекта |
## Основные моменты
- Id category и tag следуют реальной форме
`urn:vmomi:InventoryServiceCategory:…` /
`urn:vmomi:InventoryServiceTag:…:GLOBAL`.
- Строки живут в `vsphere_tag_categories`, `vsphere_tags`,
`vsphere_tag_associations` — устойчивы между перезапусками, заменяются
при reseed.
- Seed создаёт две categories (`Environment`, `Owner`) с тегами `prod`/
`staging`/`platform` и прикрепляет `prod` к двум seeded VM
(`seed_platform_extras` в
[`app/vsphere/domain/content.py`](../../../app/vsphere/domain/content.py)).
- Attach/create тега требует привилегии
`InventoryService.Tagging.CreateCategory` / `.CreateTag` / `.AttachTag`
см. [Авторизация](authz.md).
+38
View File
@@ -0,0 +1,38 @@
**Language / Язык:** [English](../../domains/tasks.md) | [Русский](tasks.md)
# Tasks
Длительные операции (power, clone, relocate, snapshot, OVF deploy, guest
customize) возвращают CIS-style task id:
[`app/vsphere/domain/tasks.py`](../../../app/vsphere/domain/tasks.py),
[`app/vsphere/rest/tasks.py`](../../../app/vsphere/rest/tasks.py).
## Эндпоинты
| Метод | Путь | Заметки |
|---|---|---|
| GET | `/api/cis/tasks` | Список недавних задач (до 200 последних) |
| GET | `/api/cis/tasks/{task}` | Status, progress, `service`/`operation`, `result`/`error` |
## Паттерн клиента
1. Мутация `POST`/`DELETE` → прочитайте task id из `{ "task": "task-…" }`
(REST) или SOAP MoRef `*_Task`.
2. Опрашивайте `GET /api/cis/tasks/{task}`, пока `status` не станет
`SUCCEEDED` или `FAILED`.
3. В `result` — результат операции (например `{"vm": "vm-104"}` при
create/clone/deploy).
## Основные моменты
- Строки задач коммитятся в `vsphere_tasks` (`id`, `description`, `status`,
`service`, `operation`, `result`, `error`, `completed_at`).
- `progress` синтезируется как `50` во время выполнения и `100` в терминальном
состоянии — дробный progress этот симулятор не моделирует.
- Одно и то же хранилище задач обслуживает и REST `/api/cis/tasks`, и SOAP
task MoRefs, поэтому Terraform apply (SOAP `CreateVM_Task`) и REST-опрос
того же id видят согласованное состояние.
- Длительности симуляции учитывают `SIMULATION_TIME_SCALE`
(больше = быстрее завершение).
См. [Поверхность API](../api-surface.md) и [Эксплуатация](../operations.md).
+50
View File
@@ -0,0 +1,50 @@
**Language / Язык:** [English](../../domains/vm.md) | [Русский](vm.md)
# Виртуальные машины
Полный REST lifecycle для объектов `VirtualMachine`:
[`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).
## Эндпоинты
| Метод | Путь | Заметки |
|---|---|---|
| GET | `/api/vcenter/vm` | Список с фильтрами `names`/`power_states`/`hosts`/`folders`/`datacenters`/`clusters`/`resource_pools`/`limit`/`cursor` |
| GET/DELETE | `/api/vcenter/vm/{vm}` | Get / delete (должна быть 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` — возвращает `{ "task": "task-…" }` |
| GET | `/api/vcenter/vm/{vm}/hardware` | Сводка |
| GET/PATCH | `/api/vcenter/vm/{vm}/hardware/cpu` \| `/memory` | Смена CPU count / memory (privilege-gated) |
| GET/POST | `/api/vcenter/vm/{vm}/hardware/disk` \| `/ethernet` | Добавить 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` | Возвращают задачу |
| GET/POST | `/api/vcenter/vm/{vm}/tools` | Статус guest tools / upgrade |
| GET | `/api/vcenter/vm/{vm}/guest/identity` \| `/networking` | Имя guest OS, синтетический IP |
| GET/POST | `/api/vcenter/vm/{vm}/guest/power` | Guest-level power ops |
| POST | `/api/vcenter/vm/{vm}/guest/customization` | Спека customization в стиле sysprep/cloud-init |
| POST | `/api/vcenter/vm/{vm}/console/tickets` | Console-тикет (стиль VNC/WebMKS) |
| GET/PUT/DELETE | `/api/vcenter/vm/{vm}/guest/filesystem` | Lab virtual guest filesystem (потоки write-a-file Ansible/Terraform) |
| GET | `/api/vcenter/vm/{vm}/guest/filesystem/files` \| `/guest/local-filesystem` | Listing |
## Основные моменты
- У каждой строки VM реалистичная форма устройств: `nics`, `disks`, `cdroms`,
`floppies`, `serials`, `scsi_adapters`, `boot`/`boot_devices`, `identity`
(`instance_uuid`, `bios_uuid`) и синтетическая карта `guest_ip` /
`guest_filesystems` — те же поля питают и REST hardware-эндпоинты, и SOAP
`VirtualMachineConfigInfo`.
- Create требует `VirtualMachine.Inventory.Create`; delete требует
`VirtualMachine.Inventory.Delete` **и** VM должна быть `POWERED_OFF`.
- Power/clone/snapshot/relocate/customize создают устойчивую CIS-задачу (см.
[Tasks](tasks.md)), а не мутируют синхронно в теле ответа.
- Console tickets из `/api/vcenter/vm/{vm}/console/tickets` живут в
`vsphere_console_tickets` (миграция `013`).
- MOID следуют конвенции `vm-{100+n}`, засеваемой
[`app/vsphere/profiles.py`](../../../app/vsphere/profiles.py).
Семантика datastore/disk-file — [Storage](storage.md); эквивалентные
операции `CreateVM_Task`/`PowerOnVM_Task`/… для pyvmomi, govmomi, Terraform и
Pulumi — [SOAP / VIM](soap.md).
+23
View File
@@ -0,0 +1,23 @@
**Language / Язык:** [English](../../examples/ansible.md) | [Русский](ansible.md)
# Ansible
Playbook использует модуль `uri` против HTTPS-шлюза
(`https://localhost`): вход по Basic-auth сессии, затем вызовы с
заголовком `vmware-api-session-id` для остального жизненного цикла.
```bash
cd examples/ansible
ansible-playbook -i inventory.ini vsphere_playbook.yml
```
[`vsphere_playbook.yml`](../../../examples/ansible/vsphere_playbook.yml) охватывает:
вход в сессию, список ВМ, создание, power on, опрос CIS-задачи
(`/api/cis/tasks/{task}`), запись файла в лабораторную гостевую виртуальную ФС,
power off, удаление и выход из сессии.
Перед опорой на фиксированные имена ВМ/MOID из предыдущего запуска выполните
повторный seed симулятора (`make seed`).
Для lab-набора на официальном `pulumi-vsphere` (непустые export'ы, HTML-отчёт)
см. [`pulumi-tests/`](../../../pulumi-tests/README.ru.md) или `make pulumi-tests`.
+21
View File
@@ -0,0 +1,21 @@
**Language / Язык:** [English](../../examples/go.md) | [Русский](go.md)
# Go
Использует стандартную библиотеку Go (`net/http`) против
`https://localhost` с Basic-auth сессией
(`vmware-api-session-id`).
```bash
cd examples/go
go run .
```
Переопределите значения по умолчанию через `VSPHERE_BASE`, `VSPHERE_USER`,
`VSPHERE_PASSWORD`, `VSPHERE_VM_NAME`. См. [`main.go`](../../../examples/go/main.go)
для потока session → list → create → power → wait-task → delete и вспомогательной
функции `waitTask`, которая опрашивает `GET /api/cis/tasks/{task}`.
Проверка TLS отключена в HTTP-клиенте только для локального самоподписанного
сертификата разработческого шлюза — не переиспользуйте такой transport против
реального vCenter.
+22
View File
@@ -0,0 +1,22 @@
**Language / Язык:** [English](../../examples/java.md) | [Русский](java.md)
# Java
Cookbook на Java 11+ `HttpClient` с Basic-auth сессией
(`vmware-api-session-id`) против `https://localhost`. Без сторонних
JSON-библиотек — ответы разбираются простым строковым извлечением полей,
достаточным для лабораторного smoke.
```bash
cd examples/java
javac Cookbook.java && java Cookbook
```
Переопределите значения по умолчанию переменными окружения `VSPHERE_BASE`,
`VSPHERE_USER`, `VSPHERE_PASSWORD`, `VSPHERE_VM_NAME`. См.
[`Cookbook.java`](../../../examples/java/Cookbook.java) для потока session →
create → power → wait-task → delete.
Клиент устанавливает trust-all `SSLContext` только для локального
самоподписанного сертификата разработческого шлюза — не переиспользуйте его
против реального vCenter.
+53
View File
@@ -0,0 +1,53 @@
**Language / Язык:** [English](../../examples/overview.md) | [Русский](overview.md)
# Обзор примеров клиентов
## Чеклист запуска
```bash
make up
curl -skf https://localhost/health/ready
make seed
curl -sk https://localhost/api/appliance/system/version
```
## Конечные точки
| URL | Когда использовать |
|---|---|
| `https://localhost` | curl, pyvmomi, govmomi, Terraform, Pulumi, Ansible, Go, Java, Perl — всё из `examples/` |
| `http://localhost` | Лабораторный HTTP без TLS (без рукопожатия TLS) |
## Краткая справка по аутентификации
**Сессия (REST)**
```bash
SID=$(curl -sk -u 'administrator@vsphere.local:VMware1!' \
-X POST https://localhost/api/session | tr -d '"')
curl -sk -H "vmware-api-session-id: $SID" https://localhost/api/vcenter/vm
```
**SOAP Login**
```bash
python examples/python/vsphere_soap_smoke.py https://localhost
```
## Ожидание задач
Не считайте HTTP-ответ мутации достаточным признаком «ВМ запущена». Вызовы
power, clone, relocate, snapshot и OVF-deploy возвращают `{ "task": "task-…" }`;
опрашивайте `GET /api/cis/tasks/{task}`, пока `status` не станет `SUCCEEDED` или
`FAILED`. См. [Задачи](../domains/tasks.md).
## Предупреждение о повторном seed
`make seed` заменяет инвентарь PostgreSQL. После этого обновите состояние
Terraform/Pulumi/Ansible — см. [Профили seed](../seed-profiles.md).
## Дерево исполняемых примеров
См. [`examples/README.ru.md`](../../../examples/README.ru.md). Lab-набор на
официальном `pulumi-vsphere` — в
[`pulumi-tests/`](../../../pulumi-tests/README.ru.md) (`make pulumi-tests`).
+20
View File
@@ -0,0 +1,20 @@
**Language / Язык:** [English](../../examples/perl.md) | [Русский](perl.md)
# Perl
Cookbook на `HTTP::Tiny` + `JSON` с Basic-auth сессией
(`vmware-api-session-id`) против `https://localhost`.
```bash
cd examples/perl
cpanm --installdeps . # или установите HTTP::Tiny, JSON, IO::Socket::SSL вручную
perl cookbook.pl
```
Переопределите значения по умолчанию переменными окружения `VSPHERE_BASE`,
`VSPHERE_USER`, `VSPHERE_PASSWORD`, `VSPHERE_VM_NAME`. См.
[`cookbook.pl`](../../../examples/perl/cookbook.pl) для потока session → list →
create → power → wait-task → delete.
`HTTP::Tiny` создаётся с `verify_SSL => 0` только для локального самоподписанного
сертификата разработческого шлюза.
+32
View File
@@ -0,0 +1,32 @@
**Language / Язык:** [English](../../examples/pulumi.md) | [Русский](pulumi.md)
# Pulumi
[`examples/pulumi/`](../../../examples/pulumi/) — Python-программа Pulumi на
официальном [`pulumi-vsphere`](https://www.pulumi.com/registry/packages/vsphere/)
(SOAP/VIM) против симулятора — тот же путь провайдера, что у Terraform
`hashicorp/vsphere`.
```bash
cd examples/pulumi
pip install -r requirements.txt
pulumi plugin install resource vsphere 4.17.0
pulumi stack init dev # один раз
pulumi config set server localhost
pulumi config set --secret password 'VMware1!'
pulumi up
```
Конфигурация (`pulumi config set`): `server` (по умолчанию `localhost`), `user`
(по умолчанию `administrator@vsphere.local`), `password` (secret), `datacenter`,
`datastore`, `cluster`, `network`, `vm_name` (по умолчанию `pulumi-lab-01`).
Та же осторожность при reseed, что и для Terraform: состояние PostgreSQL
симулятора и state Pulumi независимы. Закрепите major каталога для
воспроизводимого CI, если ваш workflow зависит от вывода Web UI/evidence (см.
[Версии API](../api-versions.md)) — сами runtime-маршруты доступны всегда
независимо от major.
Для lab-набора (inventory + folder + VM + tags, проверки непустых export'ов,
HTML-отчёт) см. [`pulumi-tests/`](../../../pulumi-tests/README.ru.md) или
`make pulumi-tests` из корня репозитория.
+33
View File
@@ -0,0 +1,33 @@
**Language / Язык:** [English](../../examples/python-requests.md) | [Русский](python-requests.md)
# Python — REST (requests / stdlib)
Сырой HTTP к REST-шлюзу vSphere без vendor SDK.
```bash
pip install -r examples/python/requirements.txt
python examples/python/requests_cookbook.py
```
[`requests_cookbook.py`](../../../examples/python/requests_cookbook.py)
демонстрирует общий поток session → create → wait-for-task → power on → wait →
power off → delete с помощью `requests`; идентификатор сессии передаётся в
заголовке `vmware-api-session-id`.
Для варианта без внешних зависимостей, только на стандартной библиотеке
(`urllib`), см. [`vsphere_rest_smoke.py`](../../../examples/python/vsphere_rest_smoke.py):
```bash
python examples/python/vsphere_rest_smoke.py https://localhost
```
Для комбинированного smoke REST-create + SOAP-`CreateVM_Task` + guest-filesystem
см. [`vsphere_lifecycle.py`](../../../examples/python/vsphere_lifecycle.py):
```bash
VSPHERE_BASE=https://localhost python examples/python/vsphere_lifecycle.py
```
Все три скрипта по умолчанию используют `administrator@vsphere.local` / `VMware1!`
и отключают проверку TLS только для локального самоподписанного сертификата
разработческого шлюза.
+32
View File
@@ -0,0 +1,32 @@
**Language / Язык:** [English](../../examples/terraform.md) | [Русский](terraform.md)
# Terraform
[`examples/terraform/vsphere/`](../../../examples/terraform/vsphere/) использует
официальный провайдер `hashicorp/vsphere` (SOAP `/sdk` под капотом), направленный
на локальный HTTPS-шлюз (`https://localhost`) с
`allow_unverified_ssl = true` для разработческого сертификата.
```bash
cd examples/terraform/vsphere
terraform init
TF_VAR_create_lab_vm=false terraform plan # только data sources (datacenter/cluster/datastore/network/VM)
TF_VAR_create_lab_vm=true terraform apply # также создаёт лабораторную ВМ (SOAP CreateVM_Task)
```
Значения по умолчанию (`variables.tf`): `vsphere_server = "localhost"`,
`vsphere_user = "administrator@vsphere.local"`,
`vsphere_password = "VMware1!"`, `datacenter = "Datacenter"`,
`cluster = "Cluster"`, `datastore = "datastore1"`,
`network = "VM Network"`, `vm_name = "web-01"` (ВМ из seed `small`/`large`).
Версии плагинов провайдера меняются быстро — закрепите версии в блоке
`required_providers` под то, что вы протестировали. После `make seed` обновите
или пересоздайте state, чтобы допущения об именах ВМ/MOID оставались согласованными.
Этот cookbook — отправная точка для лабораторного CI, а не сертификация каждого
resource/data source `hashicorp/vsphere` против полного реестра маршрутов. См.
[SOAP / VIM](../domains/soap.md) для точных операций, лежащих в основе create/read
путей провайдера, и
[`pulumi-tests/`](../../../pulumi-tests/README.ru.md) для lab-набора
`pulumi-vsphere` (`make pulumi-tests`).
@@ -0,0 +1,15 @@
**Language / Язык:** [English](../../examples/troubleshooting-clients.md) | [Русский](troubleshooting-clients.md)
# Устранение неполадок клиентов
| Симптом | Решение |
|---|---|
| Ошибки TLS-сертификата | Используйте `:443` с `verify=False` / `insecure`/`allow_unverified_ssl=true` **только** локально или plain HTTP `:80` |
| 401 на первом вызове | Отправляйте `Authorization: Basic …` только на `/api/session` (или SOAP `Login`); все остальные вызовы требуют `vmware-api-session-id` |
| 403 на power/create | Возможно, вы используете `readonly@vsphere.local` — переключитесь на `administrator@vsphere.local` или `operator@vsphere.local` |
| ВМ не найдена | Имена ВМ seed `small`: `web-01`, `web-02`, `db-01`, `app-01`, `jumpbox` — не числовые VMID в стиле Proxmox |
| Create возвращает MOID, а не task | REST `POST /api/vcenter/vm` синхронно возвращает MOID новой ВМ; только **power/clone/relocate/snapshot/OVF-deploy** возвращают `{ "task": "…" }` |
| Create провайдера vs task | Опрашивайте `/api/cis/tasks/{task}`; многие провайдеры (Terraform, Pulumi) уже ждут внутри — сырые HTTP/Go/Java/Perl клиенты часто забывают |
| Drift после reseed | Обновите/пересоздайте state Terraform/Pulumi/Ansible после `make seed` |
| Сессия истекла во время выполнения | Сессии имеют скользящий TTL 2 часа; выполните повторный login, если длинный скрипт простаивал дольше |
| SOAP `Login` не проходит | Убедитесь, что envelope направлен на `/sdk` с `SOAPAction` (пустая строка допустима) и `Content-Type: text/xml` |
+57
View File
@@ -0,0 +1,57 @@
**Language / Язык:** [English](../faq.md) | [Русский](faq.md)
# FAQ
## Это настоящий vCenter / ESXi?
Нет. Это симулятор API и состояния. Хосты, VM, datastores и сети —
устойчивые модели PostgreSQL, а не ESXi-хосты или процессы KVM/vmkernel.
## Вы действительно покрываете vSphere Automation API?
**Runtime** всегда обслуживает полную зарегистрированную route table (1077 маршрутов:
104 deep handlers + DB-backed stub surface для остальных) — см.
[Поверхность API](api-surface.md). **Catalog** majors 6–8 — намеренно
низкопокрытые исторические floors (2.9%9.6%); только major 9 (8.0 U2 / Automation
9.1 surface) объявлен как 100% в catalog. См.
[Версии API](api-versions.md) и [Совместимость](compatibility.md).
## Можно ли использовать это в CI для Terraform / Ansible / pyvmomi / custom clients?
Да. Это основной сценарий использования. Засейте профиль и направьте клиентов на
HTTPS gateway `:443` (REST `/api`/`/rest` или SOAP `/sdk`). См.
[Клиенты](clients.md).
## Почему некоторые NSX / Supervisor / vSAN / SAML calls «успешны» без remotes?
Эти области сохраняют **локальное, засеянное** состояние симулятора (см. таблицу
«Platform surfaces» в [Покрытие API](api-coverage.md)). Они намеренно не
обращаются к реальному NSX Manager, Tanzu Supervisor или IdP.
## Означает ли registry coverage perfect vSphere parity?
Это означает, что каждый зарегистрированный маршрут имеет устойчивый обработчик
или DB-backed stub и проходит verification suites проекта. Точное совпадение
краевых случаев с физическим ESXi-кластером может отличаться; используйте
`/ui/api/compatibility` и собственные client tests для certification claims.
## Где Web UI?
[https://localhost/](https://localhost/) после `make up` (gateway).
## Можно ли развернуть в Kubernetes?
Да. Используйте Helm chart в `helm/vmware-api-simulator` с опубликованным
образом Hub. Поддерживаются Ingress + cert-manager Let's Encrypt — см.
[Kubernetes / Helm](kubernetes.md).
## Что такое `ENABLE_PVE_STUB`?
Опциональная, выключенная по умолчанию legacy Proxmox VE `/api2/*` stub-плоскость,
унаследованная из общей platform lineage. Нативная vSphere REST/SOAP всегда
включена и является основной поверхностью проекта независимо от этого флага.
## Какие VM использует seed `small`?
`web-01`, `web-02`, `db-01`, `app-01`, `jumpbox` — см.
[Профили seed](seed-profiles.md).
+176
View File
@@ -0,0 +1,176 @@
**Language / Язык:** [English](../getting-started.md) | [Русский](getting-started.md)
# Быстрый старт
Поднимите локальную лабораторию vSphere, пройдите аутентификацию и выполните первый
цикл чтения/мутации против симулятора.
## Требования
- Docker и Docker Compose
- `make` (необязательно, но используется в документированных командах)
Python, линтеры и тесты запускаются **внутри** контейнеров. Для повседневной работы
локальный Python-инструментарий не нужен.
## Выберите путь
| Путь | Когда использовать |
|---|---|
| [Опубликованный образ](#1a-опубликованный-образ-docker-hub) | Самая быстрая лаборатория на `inecs/vmware-api-simulator` |
| [Helm / Kubernetes](kubernetes.md) | Установка в кластер с Ingress + Let's Encrypt |
| [Development checkout](#1b-development-checkout) | Вклад в код / bind-mount исходников |
## 1a. Опубликованный образ (Docker Hub)
Использует [`docker-compose.release.yml`](../../docker-compose.release.yml) — PostgreSQL +
runtime-симулятор + HTTPS gateway с Hub. Сборка исходников не нужна, но Compose
нужно запускать из **checkout этого репозитория**, чтобы смонтировались
`docker/gateway/` и `docker/tls/`. Seed выполняется автоматически после готовности
симулятора.
```bash
# из git checkout этого репозитория (нужны docker/gateway и docker/tls)
docker compose -f docker-compose.release.yml pull
docker compose -f docker-compose.release.yml up -d --wait
```
Закрепить версию:
```bash
IMAGE_TAG=0.1.0 docker compose -f docker-compose.release.yml up -d --wait
```
Make-хелперы (git checkout):
```bash
make release-up
# опциональный повторный seed: make release-seed PROFILE=small
```
| Порт хоста | Сервис |
|---|---|
| `443` | HTTPS gateway (основная точка входа vCenter) |
| `80` | HTTP lab face |
| `5434` | PostgreSQL (только localhost) |
Миграции выполняются автоматически через one-shot сервис `migrate`.
Далее — с [Дождитесь готовности](#2-дождитесь-готовности).
## 1b. Development checkout
```bash
make install
make up
```
Сервисы (полная картина — [Порты](ports.md)):
| Порт хоста | Сервис |
|---|---|
| `443` | HTTPS gateway (nginx) → simulator |
| `80` | HTTP lab face |
| `5434` | PostgreSQL (только localhost) |
Миграции применяются автоматически до готовности симулятора. Внутренний
процесс FastAPI слушает `8080` и на хост не публикуется.
## 2. Дождитесь готовности
```bash
curl -sk https://localhost/health/live
curl -sk https://localhost/health/ready
```
`/health/ready` возвращает HTTP 503, пока PostgreSQL недоступен **и** пока
не применена последняя упакованная миграция.
## 3. Засейте профиль
```bash
make seed # default: large — 10 hosts / 1000 VMs
VSPHERE_PROFILE=small make seed
```
`small` создаёт 3-хостовый кластер с пятью именованными VM (`web-01`, `web-02`,
`db-01`, `app-01`, `jumpbox`), datastores, standard portgroup и четырьмя
лабораторными принципалами. Другие размеры — [Профили seed](seed-profiles.md).
## 4. Проверьте версию API
```bash
curl -sk https://localhost/api/appliance/system/version | jq .
```
Catalog major при холодном старте по умолчанию — **9** (vSphere 8.0 U2 /
поверхность Automation 9.1) в Docker Compose. Просмотр и hot-swap majors 69 —
из Web UI или [Версии API](api-versions.md).
## 5. Аутентификация
```bash
SID=$(curl -sk -u 'administrator@vsphere.local:VMware1!' \
-X POST https://localhost/api/session | tr -d '"')
echo "$SID"
```
`SID` — это `vmware-api-session-id`. Передавайте его в каждом последующем
вызове как заголовок (или опирайтесь на cookie, которую также выставляет
ответ login):
```bash
curl -sk -H "vmware-api-session-id: $SID" https://localhost/api/vcenter/vm
```
Подробности: [Аутентификация](authentication.md).
## 6. Список VM и включение одной
```bash
curl -sk -H "vmware-api-session-id: $SID" \
https://localhost/api/vcenter/vm | jq .
curl -sk -X POST -H "vmware-api-session-id: $SID" \
"https://localhost/api/vcenter/vm/vm-104/power?action=start" | jq .
```
Power-действия и другие длительные операции возвращают CIS task id.
Опрашивайте задачу до завершения:
```bash
curl -sk -H "vmware-api-session-id: $SID" \
"https://localhost/api/cis/tasks/${TASK_ID}" | jq .
```
## 7. Откройте Web UI
Откройте [https://localhost/](https://localhost/) — интерактивная
консоль, каталог эндпоинтов (vSphere majors 69), вид совместимости, apply
runtime-контракта и управление demo-cluster. Скриншоты светлой/тёмной темы и
полный список возможностей — [Web UI](web-ui.md).
## 8. Попробуйте клиентскую библиотеку
```bash
# from the repository root after make up + seed
python examples/python/vsphere_rest_smoke.py https://localhost
python examples/python/vsphere_soap_smoke.py https://localhost
```
Другие стеки: [Клиенты](clients.md) и [`examples/`](../../examples/README.ru.md).
## Готово, когда…
- `/health/ready` возвращает `{"status": "ok"}` (или эквивалентное OK-тело)
- `/api/appliance/system/version` сообщает версию активного catalog major
- Session login успешен для `administrator@vsphere.local`
- `/api/vcenter/vm` перечисляет seeded VM
- Power-действие возвращает task id, который доходит до `SUCCEEDED`
## Дальше
- [Конфигурация](configuration.md) — env vars, workers, размер seed
- [Версии API](api-versions.md) — hot-swap catalog majors 69
- [Клиенты](clients.md) — Python, Ansible, Terraform, Pulumi
- [Эксплуатация](operations.md) — reseed, migrate, upgrades
+166
View File
@@ -0,0 +1,166 @@
**Language / Язык:** [English](../kubernetes.md) | [Русский](kubernetes.md)
# Kubernetes / Helm
Разверните опубликованный образ runtime из Docker Hub с помощью чарта
[`helm/vmware-api-simulator`](../../helm/vmware-api-simulator).
Образ: [`inecs/vmware-api-simulator`](https://hub.docker.com/r/inecs/vmware-api-simulator)
## Требования
- Kubernetes 1.27+ (или сопоставимая версия)
- Helm 3.14+
- [Ingress NGINX](https://kubernetes.github.io/ingress-nginx/) (или другой
IngressClass с поддержкой HTTP-01)
- [cert-manager](https://cert-manager.io/), установленный на весь кластер
Пример установки cert-manager:
```bash
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.17.2/cert-manager.yaml
```
## Быстрая установка (Hub-релиз + Ingress + Let's Encrypt)
Из git checkout этого репозитория:
```bash
helm upgrade --install vmware-sim ./helm/vmware-api-simulator \
-n vmware-sim --create-namespace \
-f ./helm/vmware-api-simulator/values-ingress-example.yaml \
--set certManager.email=you@example.com \
--set ingress.hosts[0].host=vmware-sim.example.com \
--set ingress.tls[0].hosts[0]=vmware-sim.example.com \
--set secret.ticketSigningKey="$(openssl rand -hex 32)" \
--set postgresql.auth.password="$(openssl rand -hex 16)"
```
Что это делает:
1. Скачивает `inecs/vmware-api-simulator:0.1.0` (см. `image.tag` в примерном файле).
2. Устанавливает встроенный PostgreSQL 17 (`postgres:17.5-bookworm`, как и в Compose).
3. Выполняет миграции схемы в init-контейнере (идемпотентно).
4. Загружает лабораторный профиль `small` (`seed.enabled=true`).
5. Создаёт ресурсы `ClusterIssuer`:
- `letsencrypt-prod`
- `letsencrypt-staging`
6. Создаёт Ingress с
`cert-manager.io/cluster-issuer: letsencrypt-prod` и TLS-секретом
`vmware-api-simulator-tls`.
DNS для `vmware-sim.example.com` должен указывать на ваш Ingress-контроллер.
Затем:
```bash
kubectl -n vmware-sim get certificate,ingress,pods
# дождитесь Certificate READY=True
curl -sS https://vmware-sim.example.com/health/ready
open https://vmware-sim.example.com/
```
Seeded-логин по умолчанию: `administrator@vsphere.local` / `VMware1!`.
### Сначала staging (рекомендуется)
Проверьте HTTP-01, не расходуя лимиты запросов production:
```bash
helm upgrade --install vmware-sim ./helm/vmware-api-simulator \
-n vmware-sim --create-namespace \
-f ./helm/vmware-api-simulator/values-ingress-example.yaml \
--set certManager.email=you@example.com \
--set certManager.useStaging=true \
--set ingress.hosts[0].host=vmware-sim.example.com \
--set ingress.tls[0].hosts[0]=vmware-sim.example.com \
--set secret.ticketSigningKey="$(openssl rand -hex 32)"
```
Браузеры не будут доверять staging CA — используйте `curl -k` во время
тестирования. Переключите `certManager.useStaging=false` и пересоздайте
Certificate/TLS-секрет для production.
## Минимальная установка (ClusterIP + port-forward)
```bash
helm upgrade --install vmware-sim ./helm/vmware-api-simulator \
-n vmware-sim --create-namespace \
--set secret.ticketSigningKey="$(openssl rand -hex 32)" \
--set seed.enabled=true
kubectl -n vmware-sim port-forward svc/vmware-sim-vmware-api-simulator 8080:8080
```
Откройте http://127.0.0.1:8080/. Service выставляет внутренний порт
приложения (`8080`, см. [Порты](ports.md)) — чарт не запускает TLS-gateway
nginx, используемый Compose; в production выставляйте TLS перед сервисом
через Ingress, либо обращайтесь к обычному HTTP-сервису для локального
тестирования.
## Внешний PostgreSQL
```bash
helm upgrade --install vmware-sim ./helm/vmware-api-simulator \
-n vmware-sim --create-namespace \
--set postgresql.enabled=false \
--set secret.ticketSigningKey="$(openssl rand -hex 32)" \
--set secret.databaseUrl='postgresql://user:pass@pg.example.com:5432/vmware_simulator'
```
Либо используйте `secret.existingSecret` с ключами `DATABASE_URL` и
`TICKET_SIGNING_KEY`.
## Как работает выпуск TLS
Когда `certManager.enabled=true` и `certManager.createClusterIssuer=true`,
чарт создаёт объекты ACME `ClusterIssuer`, которые решают HTTP-01 через ваш
Ingress-класс. Шаблон Ingress добавляет:
```yaml
metadata:
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
tls:
- secretName: vmware-api-simulator-tls
hosts: [vmware-sim.example.com]
```
Затем cert-manager создаёт `Certificate`, проходит HTTP-01 и сохраняет пару
ключей Let's Encrypt в этом TLS-секрете. Чарт **не** устанавливает
cert-manager или Ingress-контроллер — только issuer'ы и связку с Ingress.
Если ClusterIssuer'ы уже существуют на уровне кластера, задайте:
```yaml
certManager:
enabled: true
createClusterIssuer: false
issuerName: your-existing-issuer
```
## Эксплуатация
```bash
# логи
kubectl -n vmware-sim logs -l app.kubernetes.io/instance=vmware-sim -c simulator -f
# reseed
kubectl -n vmware-sim exec deploy/vmware-sim-vmware-api-simulator -- \
python -m app.simulation.seed_cli
# SEED_VSPHERE_PROFILE через: kubectl set env ... либо --set seed.profile=demo-cluster и upgrade
# удаление
helm -n vmware-sim uninstall vmware-sim
```
## Справочник по values
См. [`helm/vmware-api-simulator/values.yaml`](../../helm/vmware-api-simulator/values.yaml)
и [README чарта](../../helm/vmware-api-simulator/README.ru.md). Связанная
документация:
- [Быстрый старт](getting-started.md) — пути через Compose
- [Эксплуатация](operations.md) — публикация в Docker Hub / release compose
- [Безопасность](security.md) — лабораторные учётные данные и граница доверия
- [Порты](ports.md) — внутренний `8080` в сравнении с опубликованными портами gateway
+47
View File
@@ -0,0 +1,47 @@
**Language / Язык:** [English](../observability.md) | [Русский](observability.md)
# Наблюдаемость
## Health
| Path | Значение |
|---|---|
| `GET /health/live` | Liveness процесса — без проверки зависимостей |
| `GET /health/ready` | База данных доступна через `database.is_ready()`; HTTP 503, если нет |
Пример:
```bash
curl -sk https://localhost/health/live
curl -sk https://localhost/health/ready
```
Реализация: [`app/observability/health.py`](../../app/observability/health.py).
## Корреляция запросов
Входящие запросы принимают или генерируют ID через `REQUEST_ID_HEADER`
(по умолчанию `X-Request-ID`). Структурированные логи содержат поля
корреляции и маскируют известные шаблоны секретов (session id, пароли,
токены в стиле ticket).
## Метрики / трейсинг
В текущем приложении **нет** endpoint для scrape `/metrics` Prometheus и
**нет** встроенного экспортера OpenTelemetry. Заметки в архитектурной
документации, где они упоминаются, описывают целевой дизайн, а не
реально поставляемую телеметрию.
Не путайте пути vSphere REST под `/api/vcenter/activity-history` или
seeded-эндпоинты health/timesync appliance с телеметрией самого процесса
симулятора — эти обработчики симулируют состояние appliance vCenter внутри
PostgreSQL, а не собственные метрики этого процесса.
## Evidence совместимости
Отчёты о совместимости в эксплуатации:
- `/ui/api/compatibility?major=N`
Также доступны через панель совместимости Web UI. См.
[Совместимость](compatibility.md).
+151
View File
@@ -0,0 +1,151 @@
**Language / Язык:** [English](../operations.md) | [Русский](operations.md)
# Эксплуатация
## Команды day-2
```bash
make up # запуск стека
make down # остановка стека
make restart
make logs
make dev # foreground-workflow, ориентированный на reload
make db-migrate # идемпотентные миграции
make seed # атомарный reseed (SEED_VSPHERE_PROFILE=large по умолчанию)
make shell # интерактивный контейнер с инструментами
```
## Миграции
Упорядоченные SQL-файлы применяются транзакционно и записывают контрольные
суммы SHA-256. Повторный запуск `make db-migrate` безопасен. Изменение уже
применённой миграции отклоняется. `/health/ready` остаётся недоступным, пока
не появится последняя упакованная миграция.
## Reseed
```bash
make seed # large (по умолчанию)
VSPHERE_PROFILE=small make seed
VSPHERE_PROFILE=demo-cluster make seed
```
Reseed атомарно заменяет инвентарь в PostgreSQL. Состояние внешней
автоматизации (файлы состояния Terraform, стеки Pulumi, инвентари Ansible,
кодирующие MOID/имена ВМ) может после этого разойтись — обновите или
пересоздайте эти внешние каналы. См. [Профили seed](seed-profiles.md).
## Восстановление workers
CIS task workers используют аренды PostgreSQL (`FOR UPDATE SKIP LOCKED`).
После сбоя или перезапуска просроченные аренды переиспользуются, и
незавершённая работа безопасно возобновляется. Настраиваемые параметры:
`TASK_WORKER_CONCURRENCY`, `TASK_LEASE_SECONDS`, `SIMULATION_TIME_SCALE`.
## Изменение мажора каталога по умолчанию
1. Мажор каталога по умолчанию — **9** (поверхность 8.0 U2 / Automation 9.1)
при холодном старте; это не ограничивает таблицу маршрутов runtime (см.
[Версии API](api-versions.md)).
2. Используйте «Apply as runtime» в Web UI или
`POST /ui/api/contract/apply?major=N`, чтобы переключить мажор каталога
локально для процесса, для целей просмотра/evidence.
## Резервное копирование состояния лаборатории
PostgreSQL — это система записи (system of record). Используйте обычные
backup/restore для Postgres (`pg_dump` / снимки томов), если нужно сохранить
seeded-лабораторию. Контейнеры приложения одноразовые, пока сохраняется том
базы данных.
## Публикация в Docker Hub
`make release` собирает образ **runtime** (build target `runtime`, а не
локальный bind-mounted образ `dev`) и публикует его в Docker Hub:
```bash
docker login # один раз; учётная запись должна владеть или иметь права push в DOCKERHUB_USER
make release
```
Значения по умолчанию:
| Переменная | По умолчанию | Значение |
|---|---|---|
| `DOCKERHUB_USER` | `inecs` | Namespace/организация Docker Hub |
| `IMAGE_NAME` | `vmware-api-simulator` | Имя репозитория |
| `VERSION` | из `pyproject.toml` | Тег образа |
| `PUSH_LATEST` | `1` | Также помечать/публиковать `:latest` |
Примеры:
```bash
make release
make release VERSION=0.2.0
make release DOCKERHUB_USER=myorg PUSH_LATEST=0
make release-build # локальная сборка/тегирование без публикации
```
Опубликованные теги:
- `inecs/vmware-api-simulator:<version>`
- `inecs/vmware-api-simulator:latest` (если не задано `PUSH_LATEST=0`)
## Быстрый старт с опубликованным compose-файлом
[`docker-compose.release.yml`](../../docker-compose.release.yml) скачивает
runtime-образ из Hub и запускает PostgreSQL + migrate + симулятор + HTTPS
gateway:
```bash
docker compose -f docker-compose.release.yml up -d
docker compose -f docker-compose.release.yml run --rm --entrypoint python \
simulator -m app.simulation.seed_cli
curl -sk https://localhost/health/ready
open https://localhost/
```
Вспомогательные команды из git checkout:
```bash
make release-up
make release-seed PROFILE=small
make release-down
```
Полезные переопределения:
| Переменная | По умолчанию | Значение |
|---|---|---|
| `DOCKER_IMAGE` | `inecs/vmware-api-simulator` | Репозиторий образа |
| `IMAGE_TAG` | `latest` | Тег для скачивания |
| `HTTP_PORT` | `80` | Порт хоста для HTTP |
| `HTTPS_PORT` | `443` | Порт хоста для HTTPS |
| `POSTGRES_PORT` | `127.0.0.1:5434` | Bind хоста для Postgres |
| `TICKET_SIGNING_KEY` | лабораторное значение по умолчанию | Меняйте вне игрушечных лабораторий |
| `POSTGRES_PASSWORD` | `vmware` | Пароль БД |
Для Kubernetes с публичным TLS (cert-manager / Let's Encrypt) используйте
Helm-чарт — см. [Kubernetes / Helm](kubernetes.md).
## Обновления
1. Скачайте / пересоберите образы (`make install` / `make docker-build` по
ситуации).
2. Выполните миграции (`make db-migrate`).
3. Убедитесь, что `/health/ready` отвечает нормально.
4. Перепроверьте `/ui/api/compatibility?major=9` и
`/api/appliance/system/version`.
5. При необходимости заново запустите `make test-vsphere` /
`make vsphere-matrix`, если проверяете поверхность после обновления.
## Сброс лаборатории
```bash
make seed PROFILE=small
# или через UI: unload demo → small, затем снова seed
```
Для жёсткого сброса базы данных используйте `make db-reset` (деструктивно —
см. справку Makefile).
+50
View File
@@ -0,0 +1,50 @@
**Language / Язык:** [English](../ports.md) | [Русский](ports.md)
# Порты vCenter в этом симуляторе
Справочник: [vSphere Networking Ports](https://ports.esp.vmware.com/) (vCenter Server).
`api-gateway` (nginx) публикует **основной HTTPS-listener vCenter** плюс
HTTP-грань для лабораторных нужд. Каждый опубликованный порт проксирует к
одному и тому же процессу FastAPI, который сам маршрутизирует по path REST
(`/api`, `/rest`) и SOAP (`/sdk`) — отдельного порта на протокол нет. Gateway
также выставляет `X-VMware-Service` / `X-Forwarded-Port`, чтобы клиенты и
будущие роутеры могли определить, какой порт был использован.
## Опубликовано через Compose (`api-gateway`)
| Сервис | Порт контейнера | Порт хоста (dev compose) |
|---|---:|---:|
| HTTP-грань для лабораторных нужд | 80 | 80 |
| vCenter HTTPS (основная точка входа UI/API) | 443 | 443 |
Порты хоста совпадают с реальными defaults vCenter, чтобы удалённые клиенты
ходили на `https://<host>/` и `http://<host>/` без нестандартного порта.
При необходимости переопределяйте в release compose через `HTTP_PORT` /
`HTTPS_PORT`.
Также публикуется Compose (не через gateway):
| Сервис | Порт хоста (dev compose) |
|---|---:|
| PostgreSQL | `5434` (только localhost) |
Внутренний процесс симулятора (не публикуется на хост): `8080`.
## Раскладка путей на HTTPS
| Поверхность | Префикс пути | Статус |
|---|---|---|
| vSphere REST | `/api/…`, `/rest/…` | реализовано (базовый инвентарь + сессия) |
| SOAP / VIM SDK | `/sdk` | реализовано (подмножество RetrieveServiceContent / Login / RetrieveProperties) |
| HttpNfcLease / NFC | `/nfc/…` | lab transfer handshake на том же HTTPS-слушателе |
| Лабораторная консоль | `/` | да |
| Health | `/health/live`, `/health/ready` | да |
## Задокументировано, но пока не опубликовано
| Сервис | Порты |
|---|---|
| VAMI / управление appliance | 5480 |
| Управление хостом ESXi (если будет симулировано позже) | 443 (отдельный хост) |
| Syslog / прочее | разное |
+57
View File
@@ -0,0 +1,57 @@
**Language / Язык:** [English](../security.md) | [Русский](security.md)
# Безопасность
## Модель угроз лаборатории
Этот проект — **локальный / CI лабораторный симулятор**. Он не защищён как
multi-tenant публичный сервис vCenter. Учётные данные по умолчанию, демо-
элементы управления в UI и endpoint'ы совместимости удобны для разработки и
намеренно открыты в стандартном стеке Compose.
Не публикуйте порты `443` / `80` в недоверенные сети без дополнительных
средств защиты, которые вы предоставляете самостоятельно.
## Учётные данные и секреты
- Пароли хранятся как хэши scrypt (`vsphere_credentials.password_hash`).
- Session id — это непрозрачные токены (`vmware-api-session-id`) со
скользящим сроком действия 2 часа, отслеживаемые в PostgreSQL
(`vsphere_sessions`).
- Логи маскируют распознанные представления session id и паролей.
- Ответы сессий обновления/загрузки content library раскрывают только
endpoint'ы загрузки/скачивания, а не сырые секреты.
Меняйте `TICKET_SIGNING_KEY` для любой общей лаборатории. Заменяйте seeded-
пароли перед демонстрацией другим людям.
## Материалы TLS
`docker/tls/` содержит закоммиченный self-signed сертификат для локального
сервиса nginx `api-gateway`. Он существует, чтобы немодифицированные
TLS-клиенты (pyvmomi, govmomi, провайдер Terraform `hashicorp/vsphere`) могли
подключаться с установленным `insecure`/`verify=False`. **Никогда** не
используйте эти файлы повторно в production.
## Администрирование симулятора
На данный момент **нет** отдельно аутентифицируемой административной
control plane. Вспомогательные маршруты Web UI под `/ui/api/*` доступны,
когда процесс достижим по сети, — включая действия reseed и hot-swap.
Считайте сетевую доступность границей доверия.
## Авторизация
Мутирующие REST-эндпоинты проверяют привилегии, производные от роли
(`app/vsphere/security/authz.py`), прежде чем обращаться к инвентарю.
Seeded-принципал `readonly@vsphere.local` не может включать/создавать/
удалять ВМ (HTTP 403). См. [Авторизация](domains/authz.md).
## Симулированные внешние системы
Заменители NSX/Supervisor/vSAN/SAML-OIDC/VECS-сертификатов (см.
[Покрытие API](api-coverage.md)) сохраняют только локальное состояние
симулятора. Они не открывают реальных соединений с внешними IdP, NSX
Manager или живым кластером vSAN. Не полагайтесь на симулятор для
тестирования защиты от эксфильтрации живых учётных данных против реальных
провайдеров.
+76
View File
@@ -0,0 +1,76 @@
**Language / Язык:** [English](../seed-profiles.md) | [Русский](seed-profiles.md)
# Профили seed
Seed **атомарно** заменяет инвентарь vSphere, используя детерминированные
MOID, чтобы лаборатории были воспроизводимыми. Определения находятся в
[`app/vsphere/profiles.py`](../../app/vsphere/profiles.py).
```bash
make seed # по умолчанию: large (10 хостов / 1000 ВМ)
VSPHERE_PROFILE=small make seed
```
## Профили
| Профиль | Содержимое |
|---|---|
| `small` | 3 хоста ESXi, 2 datastore, 2 сети, один datacenter/cluster/resource-pool и пять именованных ВМ: `web-01`, `web-02`, `db-01`, `app-01`, `jumpbox` (смешанные состояния питания). Используется unit/integration-тестами. |
| `large` (по умолчанию) | Настраиваемое число хостов/ВМ (`SEED_VSPHERE_LARGE_HOSTS` по умолчанию 10, `SEED_VSPHERE_LARGE_VMS` по умолчанию 1000), 4 datastore, 4 сети/portgroup, `VmwareDistributedVirtualSwitch`, папки ВМ production/staging/templates. Первые пять ВМ совпадают по именам с `small` для стабильности кулинарных книг; остальные генерируются (префиксы ролей `web-`, `app-`, `db-`, `cache-`, `batch-`, `jump-`, `ci-`, `mon-`, `log-`, `ml-`). |
| `demo-cluster` | `large` с 20 хостами / 1000 ВМ — набор данных в форме предприятия для демо UI. |
Каждый профиль также загружает четыре лабораторные учётные записи, права,
привязанные к ролям (см. [Авторизация](domains/authz.md)), и — там, где
существуют таблицы платформы — стартовую content library, категории/теги
тегирования и метаданные файлов datastore (`seed_platform_extras`).
## Примеры
```bash
make seed # large, 10 хостов / 1000 ВМ
VSPHERE_PROFILE=small make seed
VSPHERE_PROFILE=demo-cluster make seed
VSPHERE_PROFILE=large VSPHERE_HOSTS=20 VSPHERE_VMS=5000 make seed
```
Либо запустите CLI seed напрямую с базовыми переменными окружения (например,
из скрипта без `make` или на шаге CI):
```bash
SEED_VSPHERE_PROFILE=small \
docker compose run --rm --entrypoint python simulator -m app.simulation.seed_cli
```
## Форма топологии
Каждый профиль строит один и тот же скелет (папка `Datacenters`
`Datacenter` → подпапки host/vm/datastore/network → один
`ClusterComputeResource` + `ResourcePool`), затем масштабирует хосты,
datastore, portgroup и ВМ. MOID ВМ имеют вид `vm-{100+n}`; MOID хостов —
`host-{10+n}`; каждая ВМ несёт одинаковую форму оборудования, используемую
как REST (`hardware/*`), так и SOAP (`VirtualMachineConfigInfo`) ответами —
NIC, диски, CD-ROM, порядок загрузки и синтетический guest IP/файловая
система.
## Демо-кластер через UI
Интерактивная консоль может загружать демо-набор данных и делать reseed по
запросу:
- `POST /ui/api/demo/load` — загружает `demo-cluster`
- `POST /ui/api/demo/unload` — очищает состояние, созданное через API, затем
загружает `small`
- `GET /ui/api/demo/state`
- `POST /ui/api/vsphere/seed?profile=small|large|demo-cluster` — reseed
любого профиля
Эти вспомогательные эндпоинты UI ориентированы на разработку и сегодня не
имеют отдельной аутентификации. Считайте их только лабораторными органами
управления.
## Reseed в сравнении с состоянием клиентов
Terraform, Pulumi и Ansible могут по-прежнему хранить состояние ресурсов
после reseed (MOID и имена ВМ могут измениться). Выполните refresh или
destroy/recreate внешнего состояния после замены инвентаря PostgreSQL. См.
[Эксплуатация](operations.md) и [Клиенты](clients.md).
+75
View File
@@ -0,0 +1,75 @@
**Language / Язык:** [English](../troubleshooting.md) | [Русский](troubleshooting.md)
# Устранение неполадок
## Ready остаётся недоступным
1. Проверьте Postgres: `make logs` / health в Compose.
2. Выполните `make db-migrate`.
3. Снова вызовите `/health/ready`.
Task workers могут повторять попытки, пока миграции не догонят после позднего migrate.
## Неожиданный HTTP 501
У каждого зарегистрированного маршрута должен быть реальный обработчик или
DB-backed стаб — 501 не должен появляться для известного пути. Если вы его видите:
- Убедитесь, что вызываете точный зарегистрированный path/verb (проверьте
`app/vsphere/rest/coverage.py` или `/docs`).
- 501 от опционального legacy-стаба (`ENABLE_PVE_STUB=true`) ожидается для
необъявленных методов в стиле PVE, когда `CONTRACT_FALLBACK=error`; это
не относится к native vSphere-поверхности.
- Сообщите о регрессии — на native vSphere-плоскости ожидается полное
покрытие реестра.
## 401 / 403
- Сессия истекла (скользящий TTL 2 часа) или заголовок/cookie
`vmware-api-session-id` не отправлен.
- Некорректный Basic auth на `/api/session` (отсутствует заголовок, неверный
base64 от `user:password`).
- Отказ по правам — попробуйте сравнить `administrator@vsphere.local` и
`readonly@vsphere.local` (см. [Авторизация](domains/authz.md)).
## Задача никогда не завершается
- Изучите `/api/cis/tasks/{task}`.
- Проверьте логи worker/симулятора (`make logs`).
- Убедитесь, что `TASK_WORKER_CONCURRENCY` > 0 и аренды в базе данных можно
забрать (claim).
- Очень высокий `SIMULATION_TIME_SCALE` даёт необычные замедления (больше =
быстрее симуляция); чаще виноваты неверно заданные worker-аренды.
## Сбои TLS / gateway
- Используйте порт хоста **443** (gateway) для TLS-клиентов — pyvmomi,
govmomi, провайдер Terraform `hashicorp/vsphere`, Pulumi.
- Устанавливайте `verify_ssl=False` / `allow_unverified_ssl=true` **только**
для локального self-signed development-сертификата.
- Внутри Compose обращайтесь напрямую к `simulator:8080` (обычный HTTP, без
gateway).
- Seeded-имена ВМ для `small``web-01`, `web-02`, `db-01`, `app-01`,
`jumpbox`, а не Proxmox-style `pve01`/VMID.
## Drift Terraform / Pulumi / Ansible после reseed
Reseed заменяет инвентарь в PostgreSQL (MOID-ы и имена ВМ могут измениться);
состояние внешних инструментов автоматически не обновляется. Выполните
refresh, import или пересоберите стеки после `make seed`.
## Hot-swap «ничего не сделал»
- Просмотр каталога ≠ apply. Используйте **Apply as runtime** или
`POST /ui/api/contract/apply?major=N`.
- Применение мажора меняет **каталог Web UI / представление evidence**, а не
живую таблицу маршрутов — runtime всегда обслуживает полную
зарегистрированную поверхность. См. [Версии API](api-versions.md).
- Apply локален для процесса; перезапуск Compose возвращает к значению по
умолчанию (мажор 9).
## Demo unload удивил
`POST /ui/api/demo/unload` очищает состояние, созданное через API, и
загружает `small`. Повторите `make seed` (или снова загрузите
`demo-cluster`), чтобы восстановить более богатую фикстуру.
+68
View File
@@ -0,0 +1,68 @@
**Language / Язык:** [English](../web-ui.md) | [Русский](web-ui.md)
# Web UI
Откройте [https://localhost/](https://localhost/) после `make up`
(gateway).
Внутренний порт симулятора — `8080`; лабораторный UI также доступен на этом хосте.
UI — это лабораторная консоль для симулятора **vSphere**, а не замена
vSphere Client. Она поддерживает светлую и тёмную темы, мажоры каталога
**69** (уровни vSphere 7–8.0U2), редактирование запроса/ответа, историю и
применение runtime-контракта.
## Возможности
- Дерево endpoint'ов и селектор метода, управляемые выбранным мажором каталога
- Параметры и примеры payload, производные от контракта
- Редактор запроса, просмотрщик ответа и история
- Вход в сессию через `POST /api/session` (Basic) → заголовок/cookie
`vmware-api-session-id`
- Сводка окружения (версия runtime, хосты, ВМ, кластеры, datastore, сети)
- Предпросмотр запросов в виде curl
- Индикатор покрытия для реализованного реестра REST
- Hot-swap **Apply as runtime** для активного уровня мажора
- Загрузка demo / seed (профили large / demo-cluster)
- Компактная консоль на `/console.html`
- Ссылка на OpenAPI по адресу `/docs`
## Аутентификация (лаборатория)
| Пользователь | Пароль | Роль |
|---|---|---|
| `administrator@vsphere.local` | `VMware1!` | Administrator |
| `readonly@vsphere.local` | `VMware1!` | ReadOnly |
| `operator@vsphere.local` | `VMware1!` | VirtualMachinePowerUser |
| `vmadmin@vsphere.local` | `VMware1!` | VirtualMachineAdministrator |
После входа кнопка Send автоматически прикладывает `vmware-api-session-id`.
## Вспомогательные методы backend
| Метод | Path | Назначение |
|---|---|---|
| GET | `/ui/api/versions` | Мажоры каталога в сравнении с runtime |
| GET | `/ui/api/catalog?major=N` | Каталог для мажора 6–9 |
| GET | `/ui/api/method?...` | Метаданные одного метода |
| GET | `/ui/api/compatibility?major=N` | Payload покрытия |
| POST | `/ui/api/contract/apply?major=N` | Hot-swap runtime-контракта |
| GET | `/ui/api/demo/state` | Состояние демо-набора данных |
| POST | `/ui/api/demo/load` | Загрузить `demo-cluster` |
| POST | `/ui/api/vsphere/seed?profile=…` | Reseed `small` / `large` / `demo-cluster` |
## Workflow работы с версиями
1. Выберите мажор **6 / 7 / 8 / 9** в каталоге.
2. Изучите методы и покрытие.
3. Используйте **Apply as runtime**, когда нужно, чтобы живые маршруты были
ограничены уровнем этого мажора.
4. Подтвердите через `/api/appliance/system/version` и `/ui/api/compatibility`.
Hot-swap хранится только в памяти; перезапуск восстанавливает настройки по
умолчанию. Подробности: [Версии API](api-versions.md).
## Замечание о безопасности
Эндпоинты UI и demo предназначены для локальной разработки. В текущей
сборке они не защищены отдельным admin-токеном. Не выставляйте порт
симулятора в недоверенные сети.