Initial commit: VMware vSphere API simulator scaffold.
Add the FastAPI app, PostgreSQL migrations, Docker/Helm packaging, API contracts, docs, client examples, and the unit/integration/compatibility test suite for local client and tooling labs without a real vCenter.
This commit is contained in:
@@ -0,0 +1,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 6–9 и 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`).
|
||||
@@ -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 по-прежнему отвечают, но не симулируются
|
||||
глубоко.
|
||||
@@ -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 в сравнении с реализованным.
|
||||
@@ -0,0 +1,77 @@
|
||||
**Language / Язык:** [English](../api-versions.md) | [Русский](api-versions.md)
|
||||
|
||||
# Версии API (vSphere catalog majors 6–9)
|
||||
|
||||
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).
|
||||
@@ -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 **6–9** соответствуют 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)
|
||||
@@ -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 в этом репозитории.
|
||||
@@ -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).
|
||||
@@ -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 6–9, основной 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`.
|
||||
@@ -0,0 +1,79 @@
|
||||
**Language / Язык:** [English](../compatibility.md) | [Русский](compatibility.md)
|
||||
|
||||
# Совместимость
|
||||
|
||||
Этот документ объясняет, как симулятор заявляет совместимость с vSphere
|
||||
Automation API по мажорам каталога **6–9**. Когда процесс запущен,
|
||||
предпочитайте живые отчёты.
|
||||
|
||||
## Живые отчёты
|
||||
|
||||
| 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).
|
||||
@@ -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 (1–32) |
|
||||
| `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).
|
||||
@@ -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`).
|
||||
@@ -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-скрипты могли
|
||||
проверить доступность до аутентификации.
|
||||
@@ -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).
|
||||
@@ -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).
|
||||
@@ -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).
|
||||
@@ -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.
|
||||
@@ -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).
|
||||
@@ -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).
|
||||
@@ -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.
|
||||
@@ -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).
|
||||
@@ -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).
|
||||
@@ -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).
|
||||
@@ -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`.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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`).
|
||||
@@ -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` только для локального самоподписанного
|
||||
сертификата разработческого шлюза.
|
||||
@@ -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` из корня репозитория.
|
||||
@@ -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 только для локального самоподписанного сертификата
|
||||
разработческого шлюза.
|
||||
@@ -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` |
|
||||
@@ -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).
|
||||
@@ -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 6–9 —
|
||||
из 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 6–9), вид совместимости, 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 6–9
|
||||
- [Клиенты](clients.md) — Python, Ansible, Terraform, Pulumi
|
||||
- [Эксплуатация](operations.md) — reseed, migrate, upgrades
|
||||
@@ -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
|
||||
@@ -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).
|
||||
@@ -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).
|
||||
@@ -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 / прочее | разное |
|
||||
@@ -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. Не полагайтесь на симулятор для
|
||||
тестирования защиты от эксфильтрации живых учётных данных против реальных
|
||||
провайдеров.
|
||||
@@ -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).
|
||||
@@ -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`), чтобы восстановить более богатую фикстуру.
|
||||
@@ -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. Она поддерживает светлую и тёмную темы, мажоры каталога
|
||||
**6–9** (уровни 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-токеном. Не выставляйте порт
|
||||
симулятора в недоверенные сети.
|
||||
Reference in New Issue
Block a user