Initial commit: stateful OpenStack API laboratory simulator.
Ship Keystone auth, multi-service handlers (Yoga→Dalmatian), Compose/Helm packaging, API contract packs, and pytest/Pulumi coverage labs.
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
**Language / Язык:** [English](README.md) | [Русский](ru/README.md)
|
||||
|
||||
# Documentation
|
||||
|
||||
Guides for the OpenStack API Simulator laboratory. Switch language with the
|
||||
header on each page. Russian mirrors live under [`ru/`](ru/README.md).
|
||||
|
||||
| Guide | Topic |
|
||||
|---|---|
|
||||
| [Getting started](getting-started.md) | First lab session (Compose) |
|
||||
| [Kubernetes / Helm](kubernetes.md) | Cluster install, Ingress, cert-manager |
|
||||
| [Configuration](configuration.md) | Env vars, Compose, Helm knobs |
|
||||
| [Authentication](authentication.md) | Keystone tokens & seeded users |
|
||||
| [Ports](ports.md) | Real OpenStack API ports (1:1 host publish) |
|
||||
| [API surface](api-surface.md) | Specialized vs schema packs |
|
||||
| [API versions](api-versions.md) | Yoga → Dalmatian series |
|
||||
| [API coverage](api_coverage.md) | Generated operation counts |
|
||||
| [Seed profiles](seed-profiles.md) | `minimal` / `demo` |
|
||||
| [Clients](clients.md) | SDK / CLI |
|
||||
| [Web UI](web-ui.md) | Console drawers |
|
||||
| [Operations](operations.md) | Day-2, release, reseed |
|
||||
| [Architecture](architecture.md) | Components & request path |
|
||||
| [Security](security.md) | Lab threat model |
|
||||
| [Observability](observability.md) | Health & logs |
|
||||
| [Troubleshooting](troubleshooting.md) | Common failures |
|
||||
| [FAQ](faq.md) | Short Q&A |
|
||||
| [Domains](domains/README.md) | Per-service notes |
|
||||
| [Examples](examples/overview.md) | Client cookbooks |
|
||||
| [Hypervisor-lab](hypervisor-lab.md) | Pulumi API coverage (all ops × series) |
|
||||
|
||||
Runnable cookbooks: [`examples/`](../examples/README.md).
|
||||
Integration suites: [`pulumi-tests/`](../pulumi-tests/README.md).
|
||||
|
||||
Back to [README](../README.md).
|
||||
@@ -0,0 +1,44 @@
|
||||
**Language / Язык:** [English](api-surface.md) | [Русский](ru/api-surface.md)
|
||||
|
||||
# API surface
|
||||
|
||||
## Surface-complete packs
|
||||
|
||||
Each OpenStack series pack lists **method + path** operations. At startup every
|
||||
unique `(method, path)` is registered as its own FastAPI route (`os-contract:…`),
|
||||
Proxmox-style. Stateful handlers from specialized modules are looked up via a
|
||||
`HandlerRegistry`; everything else falls through to the schema engine
|
||||
(`os_api_objects` lab JSON).
|
||||
|
||||
| Series | Services | Operations (approx.) |
|
||||
|---|---|---|
|
||||
| Yoga | 28 | ~1060 |
|
||||
| Antelope | 28 | ~1108 |
|
||||
| Caracal | 28 | ~1196 |
|
||||
| Dalmatian | 28 | ~1357 |
|
||||
|
||||
Authoritative numbers: [api_coverage.md](api_coverage.md).
|
||||
|
||||
## Handlers vs schema fallback
|
||||
|
||||
| Layer | Services / resources |
|
||||
|---|---|
|
||||
| **Specialized handlers** | Keystone tokens/catalog, Nova servers/flavors/keypairs/…, Neutron nets/ports/…, Glance images, Cinder volumes, Heat stacks, Swift, Ironic nodes, Octavia LBs, Placement RPs |
|
||||
| **Schema fallback** | Remaining pack collections (Barbican, Manila, Designate, Magnum, …) including nested paths |
|
||||
|
||||
## Microversions
|
||||
|
||||
Headers such as `OpenStack-API-Version: compute 2.79` and
|
||||
`X-OpenStack-Nova-API-Version` are accepted and gated per pack metadata.
|
||||
Overrides can be set in the Web UI Environment drawer.
|
||||
|
||||
## Actions
|
||||
|
||||
Nova-style `POST /servers/{id}/action` and similar pack `kind=action` ops are
|
||||
handled by the schema/action path (power state updates for common actions).
|
||||
|
||||
## Errors
|
||||
|
||||
OpenStack-shaped errors (`OpenStackError`) with `code`, `title`, `message`.
|
||||
Unknown routes that are not in the active contract pack return standard
|
||||
FastAPI `404`.
|
||||
@@ -0,0 +1,56 @@
|
||||
**Language / Язык:** [English](api-versions.md) | [Русский](ru/api-versions.md)
|
||||
|
||||
# API versions (series packs)
|
||||
|
||||
The simulator ships **four** OpenStack release series as contract packs:
|
||||
|
||||
| Series | OpenStack release family | Cold-start env |
|
||||
|---|---|---|
|
||||
| `yoga` | Yoga | `OPENSTACK_SERIES=yoga` |
|
||||
| `antelope` | Antelope | `OPENSTACK_SERIES=antelope` |
|
||||
| `caracal` | Caracal | `OPENSTACK_SERIES=caracal` |
|
||||
| `dalmatian` | Dalmatian (default) | `OPENSTACK_SERIES=dalmatian` |
|
||||
|
||||
## Cold start
|
||||
|
||||
Compose / process:
|
||||
|
||||
```bash
|
||||
OPENSTACK_SERIES=caracal docker compose up -d
|
||||
```
|
||||
|
||||
Helm:
|
||||
|
||||
```bash
|
||||
--set config.openstackSeries=yoga
|
||||
```
|
||||
|
||||
## Hot-swap
|
||||
|
||||
```bash
|
||||
curl -X POST http://127.0.0.1:5000/ui/api/openstack/contracts/activate \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"series":"dalmatian"}'
|
||||
```
|
||||
|
||||
Or Web UI → Environment → OpenStack API pack → Activate.
|
||||
|
||||
Hot-swap remounts schema routes (`remount_schema_services`) without rebuilding
|
||||
the image.
|
||||
|
||||
## Pack layout
|
||||
|
||||
```
|
||||
contracts/openstack/<series>/
|
||||
manifest.json
|
||||
keystone/api.json
|
||||
nova/api.json
|
||||
neutron/api.json
|
||||
…
|
||||
```
|
||||
|
||||
Regenerate:
|
||||
|
||||
```bash
|
||||
PYTHONPATH=tools python3 tools/os_api_inventory/generate_packs.py
|
||||
```
|
||||
@@ -0,0 +1,64 @@
|
||||
**Language / Язык:** [English](api_coverage.md) | [Русский](ru/api_coverage.md)
|
||||
|
||||
# OpenStack API coverage — dalmatian
|
||||
|
||||
Generated from `contracts/openstack/dalmatian/manifest.json`.
|
||||
|
||||
- **Services:** 28
|
||||
- **Operations:** 1357
|
||||
- **Checksum:** `5d8f32baa835db2b556b6f33ac3c1b67b74db8194f00ce7d6eb8c59e3bbd7063`
|
||||
- **Generated at:** 2026-07-16T00:28:30Z
|
||||
|
||||
## Series deltas
|
||||
|
||||
| Series | Major | Operations |
|
||||
|---|---:|---:|
|
||||
| Antelope | 7 | 1108 |
|
||||
| Caracal | 8 | 1196 |
|
||||
| Dalmatian | 9 | 1357 |
|
||||
| Yoga | 6 | 1060 |
|
||||
|
||||
Older series omit paths introduced later (`tools/os_api_inventory/series_deltas.py`)
|
||||
and use lower microversion ceilings. Apply a pack in the Environment drawer to hot-swap.
|
||||
|
||||
Surface-complete means every operation in the pack is mounted by the schema engine
|
||||
(specialized routers still win on overlapping stateful paths).
|
||||
|
||||
| Service | Type | Port | Operations | Microversions |
|
||||
|---|---|---:|---:|---|
|
||||
| adjutant | admin-logic | 5050 | 24 | — |
|
||||
| aodh | alarming | 8042 | 19 | — |
|
||||
| barbican | key-manager | 9311 | 25 | — |
|
||||
| blazar | reservation | 1234 | 19 | — |
|
||||
| cinder | volumev3 | 8776 | 98 | 3.0–3.70 |
|
||||
| cloudkitty | rating | 8889 | 25 | — |
|
||||
| designate | dns | 9001 | 37 | — |
|
||||
| freezer | backup | 9090 | 31 | — |
|
||||
| glance | image | 9292 | 39 | — |
|
||||
| heat | orchestration | 8004 | 38 | — |
|
||||
| heat-cfn | cloudformation | 8000 | 8 | — |
|
||||
| ironic | baremetal | 6385 | 58 | 1.1–1.90 |
|
||||
| keystone | identity | 5000 | 77 | — |
|
||||
| magnum | container-infra | 9511 | 25 | — |
|
||||
| manila | sharev2 | 8786 | 50 | 2.0–2.82 |
|
||||
| masakari | instance-ha | 15868 | 19 | — |
|
||||
| mistral | workflowv2 | 8989 | 37 | — |
|
||||
| neutron | network | 9696 | 290 | — |
|
||||
| nova | compute | 8774 | 124 | 2.1–2.96 |
|
||||
| octavia | load-balancer | 9876 | 74 | — |
|
||||
| placement | placement | 8003 | 30 | 1.0–1.39 |
|
||||
| swift | object-store | 8080 | 10 | — |
|
||||
| tacker | nfv-orchestration | 9890 | 30 | — |
|
||||
| trove | database | 8779 | 31 | — |
|
||||
| vitrage | rca | 8999 | 30 | — |
|
||||
| watcher | infra-optim | 9322 | 49 | — |
|
||||
| zaqar | messaging | 8888 | 27 | — |
|
||||
| zun | container | 9517 | 33 | — |
|
||||
|
||||
## Core minimums
|
||||
|
||||
| Service | Required | Actual |
|
||||
|---|---:|---:|
|
||||
| keystone | 40 | 77 (OK) |
|
||||
| neutron | 70 | 290 (OK) |
|
||||
| nova | 70 | 124 (OK) |
|
||||
@@ -0,0 +1,58 @@
|
||||
**Language / Язык:** [English](architecture.md) | [Русский](ru/architecture.md)
|
||||
|
||||
# Architecture
|
||||
|
||||
## Components
|
||||
|
||||
```
|
||||
┌─────────────┐ ┌──────────────────┐ ┌────────────┐
|
||||
│ Clients │────▶│ api-gateway │────▶│ simulator │
|
||||
│ SDK / CLI │ │ nginx multi-port│ │ FastAPI │
|
||||
│ Web UI │ │ :5000,:8774,… │ │ :8080 │
|
||||
└─────────────┘ └──────────────────┘ └─────┬──────┘
|
||||
│
|
||||
┌─────▼──────┐
|
||||
│ PostgreSQL │
|
||||
└────────────┘
|
||||
```
|
||||
|
||||
| Piece | Responsibility |
|
||||
|---|---|
|
||||
| **api-gateway** | Publish OpenStack default ports; set `X-OpenStack-Service` / `X-Forwarded-Port` |
|
||||
| **ServiceDispatchMiddleware** | Rewrite to `/_os/<service>/…` |
|
||||
| **Specialized routers** | Stateful Keystone, Nova, Neutron, Glance, Cinder, Heat, Swift, Ironic, Octavia, Placement |
|
||||
| **Schema engine** | Surface-complete ops from `contracts/openstack/<series>/` |
|
||||
| **PostgreSQL** | Identity, IaaS tables, `os_api_objects` generic store |
|
||||
|
||||
## Request lifecycle
|
||||
|
||||
1. Client hits e.g. `http://host:8774/v2.1/servers`.
|
||||
2. Gateway injects service headers.
|
||||
3. Dispatch mounts the request under `/_os/nova/…`.
|
||||
4. Specialized Nova handler **or** schema pack operation runs.
|
||||
5. Reads/writes go to PostgreSQL (typed tables or `os_api_objects`).
|
||||
|
||||
## Contract packs
|
||||
|
||||
- Generated inventory → `contracts/openstack/{yoga,antelope,caracal,dalmatian}/`
|
||||
- Hot-swap via Web UI / `/ui/api/openstack/contracts/activate`
|
||||
- Coverage report: [api_coverage.md](api_coverage.md)
|
||||
|
||||
## Seed profiles
|
||||
|
||||
| Profile | Contents |
|
||||
|---|---|
|
||||
| `minimal` | Small Keystone + few IaaS resources |
|
||||
| `demo` | ~1000 servers, multi-project topology, nested collections |
|
||||
|
||||
Details: [seed-profiles.md](seed-profiles.md).
|
||||
|
||||
## Deployment model
|
||||
|
||||
| Mode | Gateway | DB |
|
||||
|---|---|---|
|
||||
| Compose | nginx container | bundled Postgres |
|
||||
| Helm | nginx Deployment + multi-port Service | bundled StatefulSet or external |
|
||||
| Ingress | TLS terminates at Ingress → gateway:5000 | — |
|
||||
|
||||
See [kubernetes.md](kubernetes.md).
|
||||
@@ -0,0 +1,80 @@
|
||||
**Language / Язык:** [English](authentication.md) | [Русский](ru/authentication.md)
|
||||
|
||||
# Authentication
|
||||
|
||||
The simulator implements **Keystone v3** password authentication and project
|
||||
scoping (lab subset).
|
||||
|
||||
## Password auth
|
||||
|
||||
```http
|
||||
POST /v3/auth/tokens
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"auth": {
|
||||
"identity": {
|
||||
"methods": ["password"],
|
||||
"password": {
|
||||
"user": {
|
||||
"name": "admin",
|
||||
"domain": {"name": "Default"},
|
||||
"password": "secret"
|
||||
}
|
||||
}
|
||||
},
|
||||
"scope": {
|
||||
"project": {"name": "demo", "domain": {"name": "Default"}}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Response:
|
||||
|
||||
- Header **`X-Subject-Token`** — use as **`X-Auth-Token`** on subsequent calls
|
||||
- Body `token.catalog` — service endpoints (ports match [ports.md](ports.md))
|
||||
|
||||
## Seeded principals
|
||||
|
||||
Password for all users: **`secret`**. Domain: **`Default`**.
|
||||
|
||||
### Minimal seed
|
||||
|
||||
| User | Projects | Role |
|
||||
|---|---|---|
|
||||
| `admin` | `admin`, `demo` | admin |
|
||||
| `demo` | `demo` | member |
|
||||
|
||||
### Demo cloud
|
||||
|
||||
| User | Typical projects |
|
||||
|---|---|
|
||||
| `admin` | all |
|
||||
| `ops` | production, staging |
|
||||
| `developer` | development, staging |
|
||||
| `demo` / `auditor` | demo / production |
|
||||
|
||||
## Unscoped / errors
|
||||
|
||||
- Missing token → `401 Unauthorized`
|
||||
- Wrong password → `401`
|
||||
- Project-scoped APIs without project scope → `401` with a clear message
|
||||
|
||||
## openstacksdk / CLI
|
||||
|
||||
```bash
|
||||
export OS_AUTH_URL=http://127.0.0.1:5000/v3
|
||||
export OS_USERNAME=admin
|
||||
export OS_PASSWORD=secret
|
||||
export OS_PROJECT_NAME=demo
|
||||
export OS_USER_DOMAIN_NAME=Default
|
||||
export OS_PROJECT_DOMAIN_NAME=Default
|
||||
export OS_IDENTITY_API_VERSION=3
|
||||
|
||||
openstack server list
|
||||
openstack network list
|
||||
```
|
||||
|
||||
Against Helm Ingress, set `OS_AUTH_URL=https://os-sim.example.com/v3`
|
||||
(and trust the certificate or use `--insecure` in labs).
|
||||
@@ -0,0 +1,46 @@
|
||||
**Language / Язык:** [English](clients.md) | [Русский](ru/clients.md)
|
||||
|
||||
# Clients
|
||||
|
||||
## Connection matrix
|
||||
|
||||
| Client | Auth URL | Notes |
|
||||
|---|---|---|
|
||||
| curl | `http://127.0.0.1:5000/v3` | Use `X-Subject-Token` → `X-Auth-Token` |
|
||||
| openstack CLI | `OS_AUTH_URL=…/v3` | See [authentication.md](authentication.md) |
|
||||
| openstacksdk | same | Service catalog ports must match gateway |
|
||||
| Terraform OpenStack provider | `auth_url` | Point at Keystone; catalog drives Nova/Neutron |
|
||||
| Ansible `openstack.*` | clouds.yaml | Same credentials as CLI |
|
||||
|
||||
## Compose (local)
|
||||
|
||||
```bash
|
||||
export OS_AUTH_URL=http://127.0.0.1:5000/v3
|
||||
export OS_USERNAME=admin
|
||||
export OS_PASSWORD=secret
|
||||
export OS_PROJECT_NAME=demo
|
||||
export OS_USER_DOMAIN_NAME=Default
|
||||
export OS_PROJECT_DOMAIN_NAME=Default
|
||||
export OS_IDENTITY_API_VERSION=3
|
||||
```
|
||||
|
||||
## Helm / Ingress
|
||||
|
||||
```bash
|
||||
export OS_AUTH_URL=https://os-sim.example.com/v3
|
||||
# Other services: either port-forward gateway ports or rely on catalog URLs
|
||||
# that your Ingress/DNS map correctly.
|
||||
```
|
||||
|
||||
For multi-port access without Ingress TCP, port-forward the gateway Service
|
||||
(see [kubernetes.md](kubernetes.md)).
|
||||
|
||||
## Examples in-repo
|
||||
|
||||
| Path | Purpose |
|
||||
|---|---|
|
||||
| `examples/python/openstack_smoke.py` | Multi-port GET smoke |
|
||||
| `examples/python/openstack_conformance.py` | Write-path sample |
|
||||
| `examples/python/openstack_surface_probe.py` | Full pack lifecycle probe |
|
||||
|
||||
Cookbooks: [examples/](examples/).
|
||||
@@ -0,0 +1,59 @@
|
||||
**Language / Язык:** [English](configuration.md) | [Русский](ru/configuration.md)
|
||||
|
||||
# Configuration
|
||||
|
||||
## Environment variables
|
||||
|
||||
| Variable | Default | Purpose |
|
||||
|---|---|---|
|
||||
| `APP_HOST` | `0.0.0.0` | Bind address |
|
||||
| `APP_PORT` | `8080` | Internal FastAPI port (not the public Keystone port) |
|
||||
| `DATABASE_URL` | (compose/helm) | PostgreSQL DSN |
|
||||
| `TICKET_SIGNING_KEY` | lab secret | Token/signing material (rotate in shared labs) |
|
||||
| `LOG_LEVEL` | `INFO` | Logging |
|
||||
| `OPENSTACK_SERIES` | `dalmatian` | Contract pack series at cold start |
|
||||
| `REQUEST_ID_HEADER` | `X-Request-ID` | Request correlation header |
|
||||
| `SEED_PROFILE` | `minimal` | Used by `seed_cli` / Helm seed Job (`minimal` / `demo`) |
|
||||
|
||||
## Compose
|
||||
|
||||
| File | Role |
|
||||
|---|---|
|
||||
| `docker-compose.yml` | Dev stack (build + bind mounts) |
|
||||
| `docker-compose.release.yml` | Published Hub image |
|
||||
| `.env` / `.env.example` | Local overrides |
|
||||
|
||||
Services:
|
||||
|
||||
- **simulator** — FastAPI on internal `8080`
|
||||
- **api-gateway** — nginx publishing real OpenStack API ports 1:1 ([ports.md](ports.md))
|
||||
- **postgres** — `postgres:17.5-bookworm` on host `127.0.0.1:5433`
|
||||
|
||||
## Helm
|
||||
|
||||
See [kubernetes.md](kubernetes.md) and
|
||||
[`helm/openstack-api-simulator/values.yaml`](../helm/openstack-api-simulator/values.yaml).
|
||||
|
||||
Important knobs:
|
||||
|
||||
| Value | Purpose |
|
||||
|---|---|
|
||||
| `gateway.enabled` | Multi-port nginx (default `true`) |
|
||||
| `config.openstackSeries` | Pack series env `OPENSTACK_SERIES` |
|
||||
| `seed.profile` | `minimal` / `demo` |
|
||||
| `postgresql.enabled` | Bundled DB |
|
||||
| `secret.ticketSigningKey` | Must be rotated for shared clusters |
|
||||
|
||||
## Contract packs
|
||||
|
||||
Location: `contracts/openstack/<series>/`.
|
||||
|
||||
Each series has per-service `api.json` packs consumed by the schema engine.
|
||||
Specialized routers (Keystone, Nova, Neutron, …) remain stateful for happy-paths.
|
||||
|
||||
## Web UI overrides
|
||||
|
||||
Environment drawer → **OpenStack API pack**:
|
||||
|
||||
- Activate series (hot remount)
|
||||
- Per-service microversion override
|
||||
@@ -0,0 +1,22 @@
|
||||
**Language / Язык:** [English](README.md) | [Русский](../ru/domains/README.md)
|
||||
|
||||
# OpenStack service domains
|
||||
|
||||
Guides for the main specialized surfaces. Pack-only services (Barbican, Manila,
|
||||
Designate, …) are covered generically by the schema engine and seeded into
|
||||
`os_api_objects` — see [api-surface.md](../api-surface.md) and
|
||||
[api_coverage.md](../api_coverage.md).
|
||||
|
||||
| Guide | Service | Port |
|
||||
|---|---|---|
|
||||
| [keystone.md](keystone.md) | Identity | 5000 |
|
||||
| [nova.md](nova.md) | Compute | 8774 |
|
||||
| [neutron.md](neutron.md) | Network | 9696 |
|
||||
| [glance.md](glance.md) | Image | 9292 |
|
||||
| [cinder.md](cinder.md) | Block storage | 8776 |
|
||||
| [placement.md](placement.md) | Placement | 8003 |
|
||||
| [heat.md](heat.md) | Orchestration | 8004 |
|
||||
| [swift.md](swift.md) | Object storage | 8080 |
|
||||
| [ironic.md](ironic.md) | Bare metal | 6385 |
|
||||
| [octavia.md](octavia.md) | Load balancer | 9876 |
|
||||
| [schema-services.md](schema-services.md) | Remaining pack services | various |
|
||||
@@ -0,0 +1,10 @@
|
||||
**Language / Язык:** [English](cinder.md) | [Русский](../ru/domains/cinder.md)
|
||||
|
||||
# Cinder (block storage)
|
||||
|
||||
Port **8776**. Paths under `/v3/` (and `/v3/{project_id}/…`).
|
||||
|
||||
## Stateful
|
||||
|
||||
Volumes CRUD. Demo cloud: ~600 volumes (`in-use` / `available`).
|
||||
Snapshots, types, backups, and related collections are pack/schema-backed.
|
||||
@@ -0,0 +1,10 @@
|
||||
**Language / Язык:** [English](glance.md) | [Русский](../ru/domains/glance.md)
|
||||
|
||||
# Glance (image)
|
||||
|
||||
Port **9292**. Paths under `/v2/`.
|
||||
|
||||
## Stateful
|
||||
|
||||
Image list/show/create/update/delete; public + project-owned images.
|
||||
Members/tags served from `os_api_objects` in the demo seed.
|
||||
@@ -0,0 +1,11 @@
|
||||
**Language / Язык:** [English](heat.md) | [Русский](../ru/domains/heat.md)
|
||||
|
||||
# Heat (orchestration)
|
||||
|
||||
Port **8004**. Paths `/v1/{tenant_id}/…`.
|
||||
|
||||
## Stateful
|
||||
|
||||
Stacks in `os_stacks`. Demo seed adds stacks plus nested
|
||||
`stack_resource` / `stack_event` / `software_config` / `software_deployment`
|
||||
rows for pack GET probes.
|
||||
@@ -0,0 +1,10 @@
|
||||
**Language / Язык:** [English](ironic.md) | [Русский](../ru/domains/ironic.md)
|
||||
|
||||
# Ironic (bare metal)
|
||||
|
||||
Port **6385**.
|
||||
|
||||
## Stateful
|
||||
|
||||
Nodes in `os_nodes`. Demo seed creates a pool of ironic nodes; ports/chassis/
|
||||
allocations are schema-backed samples.
|
||||
@@ -0,0 +1,21 @@
|
||||
**Language / Язык:** [English](keystone.md) | [Русский](../ru/domains/keystone.md)
|
||||
|
||||
# Keystone (identity)
|
||||
|
||||
Port **5000**. Paths under `/v3/`.
|
||||
|
||||
## Implemented (lab)
|
||||
|
||||
- `POST /v3/auth/tokens` — password auth, project scope
|
||||
- Catalog with multi-port endpoints
|
||||
- Projects, users, roles, role assignments (seeded + CRUD via pack/schema)
|
||||
- Domains (Default)
|
||||
|
||||
## Seed
|
||||
|
||||
Minimal and demo profiles create `Default` domain, roles `admin`/`member`, and
|
||||
users documented in [authentication.md](../authentication.md).
|
||||
|
||||
## Notes
|
||||
|
||||
Federation, application credentials, and full policy engine are out of scope.
|
||||
@@ -0,0 +1,16 @@
|
||||
**Language / Язык:** [English](neutron.md) | [Русский](../ru/domains/neutron.md)
|
||||
|
||||
# Neutron (network)
|
||||
|
||||
Port **9696**. Paths under `/v2.0/`.
|
||||
|
||||
## Stateful resources
|
||||
|
||||
Networks, subnets, ports, routers, security groups/rules, floating IPs, agents.
|
||||
|
||||
## Schema / seeded extensions
|
||||
|
||||
QoS, trunks, RBAC, address scopes, subnet pools, conntrack helpers, port
|
||||
forwardings, FWaaS/VPNaaS/BGP VPN samples in demo seed.
|
||||
|
||||
Demo adds multiple nets/SGs/routers per project for realistic list density.
|
||||
@@ -0,0 +1,20 @@
|
||||
**Language / Язык:** [English](nova.md) | [Русский](../ru/domains/nova.md)
|
||||
|
||||
# Nova (compute)
|
||||
|
||||
Port **8774**. Paths under `/v2.1/`.
|
||||
|
||||
## Stateful resources
|
||||
|
||||
Servers, flavors, keypairs, server groups, AZ, hypervisors, aggregates,
|
||||
services, migrations, volume/interface attachments, metadata, tags,
|
||||
instance actions, consoles (lab URLs).
|
||||
|
||||
## Demo cloud
|
||||
|
||||
~1000 servers across projects, metadata/`_tags`, attachments linked to volumes
|
||||
and ports.
|
||||
|
||||
## Microversions
|
||||
|
||||
Send `OpenStack-API-Version: compute X.Y` or Nova legacy header. Pack gates apply.
|
||||
@@ -0,0 +1,10 @@
|
||||
**Language / Язык:** [English](octavia.md) | [Русский](../ru/domains/octavia.md)
|
||||
|
||||
# Octavia (load balancer)
|
||||
|
||||
Port **9876**. Paths under `/v2/lbaas/…`.
|
||||
|
||||
## Stateful
|
||||
|
||||
Load balancers in `os_loadbalancers`. Listeners/pools/healthmonitors/providers/
|
||||
flavors are served from `os_api_objects` (demo seed populates them).
|
||||
@@ -0,0 +1,10 @@
|
||||
**Language / Язык:** [English](placement.md) | [Русский](../ru/domains/placement.md)
|
||||
|
||||
# Placement
|
||||
|
||||
Port **8003**.
|
||||
|
||||
## Lab behaviour
|
||||
|
||||
- `GET /resource_providers` — from demo `os_api_objects` (or fallback stub)
|
||||
- `GET/PUT /allocations/{consumer_uuid}` — persisted allocations with lab fallback
|
||||
@@ -0,0 +1,14 @@
|
||||
**Language / Язык:** [English](schema-services.md) | [Русский](../ru/domains/schema-services.md)
|
||||
|
||||
# Schema-backed services
|
||||
|
||||
These projects are primarily driven by contract packs + `os_api_objects`
|
||||
(demo seed inserts multiple rows per resource type):
|
||||
|
||||
Barbican, Manila, Designate, Magnum, Zun, Trove, Mistral, Aodh, CloudKitty,
|
||||
Freezer, Blazar, Vitrage, Masakari, Tacker, Adjutant, Watcher, Zaqar, Heat-CFN.
|
||||
|
||||
Ports: [ports.md](../ports.md). Operations: [api_coverage.md](../api_coverage.md).
|
||||
|
||||
CRUD lifecycle is exercised by `examples/python/openstack_surface_probe.py`
|
||||
and `tests/openstack/conformance/`.
|
||||
@@ -0,0 +1,10 @@
|
||||
**Language / Язык:** [English](swift.md) | [Русский](../ru/domains/swift.md)
|
||||
|
||||
# Swift (object storage)
|
||||
|
||||
Port **8080** on the **gateway** (internal simulator remains on 8080 behind nginx).
|
||||
|
||||
## Stateful
|
||||
|
||||
Accounts/containers/objects in `os_swift_*` tables. Demo seed creates
|
||||
`images` / `backups` / `artifacts` containers with a readme object per project.
|
||||
@@ -0,0 +1,20 @@
|
||||
**Language / Язык:** [English](ansible.md) | [Русский](../ru/examples/ansible.md)
|
||||
|
||||
# Ansible (openstack.cloud)
|
||||
|
||||
## Cookbook (single stack)
|
||||
|
||||
[`examples/ansible/playbook.yml`](../../examples/ansible/playbook.yml) uses
|
||||
`ansible.builtin.uri` against Keystone/Nova/Neutron/Glance — no Galaxy collections
|
||||
required. Good for a minimal “create server + metadata + cleanup” walkthrough.
|
||||
|
||||
```bash
|
||||
make up && make seed-demo
|
||||
cd examples/ansible
|
||||
ansible-playbook -i inventory.ini playbook.yml
|
||||
```
|
||||
|
||||
Auth: `http://127.0.0.1:5000/v3`, user `admin`, password `secret`, project `demo`.
|
||||
|
||||
API coverage integration suites now live under [`pulumi-tests/`](../../pulumi-tests/)
|
||||
(Pulumi / `pulumi_openstack`). See [hypervisor-lab.md](../hypervisor-lab.md).
|
||||
@@ -0,0 +1,19 @@
|
||||
**Language / Язык:** [English](openstack-cli.md) | [Русский](../ru/examples/openstack-cli.md)
|
||||
|
||||
# OpenStack CLI
|
||||
|
||||
```bash
|
||||
export OS_AUTH_URL=http://127.0.0.1:5000/v3
|
||||
export OS_USERNAME=admin
|
||||
export OS_PASSWORD=secret
|
||||
export OS_PROJECT_NAME=demo
|
||||
export OS_USER_DOMAIN_NAME=Default
|
||||
export OS_PROJECT_DOMAIN_NAME=Default
|
||||
export OS_IDENTITY_API_VERSION=3
|
||||
|
||||
openstack token issue
|
||||
openstack server list
|
||||
openstack network list
|
||||
openstack volume list
|
||||
openstack stack list
|
||||
```
|
||||
@@ -0,0 +1,53 @@
|
||||
**Language / Язык:** [English](overview.md) | [Русский](../ru/examples/overview.md)
|
||||
|
||||
# Client examples overview
|
||||
|
||||
Runnable scripts live under [`examples/`](../../examples/).
|
||||
Pulumi API coverage lab lives under [`pulumi-tests/`](../../pulumi-tests/).
|
||||
|
||||
## Quick reference
|
||||
|
||||
| Path | Tool | Purpose |
|
||||
|---|---|---|
|
||||
| `examples/python/openstacksdk_cookbook.py` | openstacksdk | net + server + volume lifecycle |
|
||||
| `examples/ansible/playbook.yml` | Ansible `uri` | minimal Keystone/Nova/Neutron |
|
||||
| `examples/terraform/main.tf` | Terraform | `openstack_compute_instance_v2` + volume |
|
||||
| `examples/pulumi/` | Pulumi | `pulumi_openstack` Instance + Network |
|
||||
| `examples/run_iac_stack.sh` | all four | sequential smoke of cookbooks |
|
||||
| `pulumi-tests/` | Pulumi | every pack operation × yoga→dalmatian + HTML report |
|
||||
|
||||
## Auth quick reference
|
||||
|
||||
1. `POST /v3/auth/tokens` → `X-Subject-Token`
|
||||
2. Call services with `X-Auth-Token` on the correct [port](../ports.md)
|
||||
|
||||
Default lab: `admin` / `secret`, project `demo`, domain `Default`.
|
||||
|
||||
## Cookbooks
|
||||
|
||||
- [Python (requests)](python-requests.md)
|
||||
- [Python (openstacksdk)](python-openstacksdk.md)
|
||||
- [Ansible](ansible.md)
|
||||
- [Terraform](terraform.md)
|
||||
- [Pulumi](pulumi.md)
|
||||
- [CLI](openstack-cli.md)
|
||||
- [Troubleshooting](troubleshooting-clients.md)
|
||||
|
||||
## API coverage lab (Pulumi)
|
||||
|
||||
Full guide: [hypervisor-lab.md](../hypervisor-lab.md)
|
||||
|
||||
```bash
|
||||
cd pulumi-tests
|
||||
make up
|
||||
make test-pulumi-smoke
|
||||
make test-pulumi
|
||||
open reports/pulumi-report.html
|
||||
```
|
||||
|
||||
Probe scripts (simulator conformance helpers):
|
||||
|
||||
| Script | Purpose |
|
||||
|---|---|
|
||||
| `examples/python/openstack_smoke.py` | Multi-port GET smoke |
|
||||
| `examples/python/openstack_surface_probe.py` | Pack operation probe (also used by Pulumi lab) |
|
||||
@@ -0,0 +1,30 @@
|
||||
**Language / Язык:** [English](pulumi.md) | [Русский](../ru/examples/pulumi.md)
|
||||
|
||||
# Pulumi (pulumi_openstack)
|
||||
|
||||
## Cookbook (single stack)
|
||||
|
||||
[`examples/pulumi/`](../../examples/pulumi/) — `pulumi_openstack` Instance,
|
||||
Network, Subnet against the simulator.
|
||||
|
||||
```bash
|
||||
make up && make seed-demo
|
||||
cd examples/pulumi
|
||||
pulumi stack init dev --secrets-provider passphrase
|
||||
export PULUMI_CONFIG_PASSPHRASE=lab
|
||||
pulumi up
|
||||
pulumi destroy
|
||||
```
|
||||
|
||||
## Coverage lab (`pulumi-tests`)
|
||||
|
||||
[`pulumi-tests/`](../../pulumi-tests/) runs `pulumi_openstack` coverage stacks for
|
||||
every series, asserts non-empty exports, then HTTP-probes pack operations with
|
||||
non-empty body checks.
|
||||
|
||||
```bash
|
||||
make pulumi-tests
|
||||
open pulumi-tests/reports/pulumi-report.html
|
||||
```
|
||||
|
||||
See [hypervisor-lab.md](../hypervisor-lab.md).
|
||||
@@ -0,0 +1,24 @@
|
||||
**Language / Язык:** [English](python-openstacksdk.md) | [Русский](../ru/examples/python-openstacksdk.md)
|
||||
|
||||
# Python + openstacksdk
|
||||
|
||||
```python
|
||||
import openstack
|
||||
|
||||
conn = openstack.connect(
|
||||
auth_url="http://127.0.0.1:5000/v3",
|
||||
project_name="demo",
|
||||
username="admin",
|
||||
password="secret",
|
||||
user_domain_name="Default",
|
||||
project_domain_name="Default",
|
||||
)
|
||||
|
||||
for server in conn.compute.servers():
|
||||
print(server.name, server.status)
|
||||
for network in conn.network.networks():
|
||||
print(network.name)
|
||||
```
|
||||
|
||||
Ensure the service catalog ports are reachable (Compose gateway or Helm
|
||||
port-forward). See [clients.md](../clients.md).
|
||||
@@ -0,0 +1,35 @@
|
||||
**Language / Язык:** [English](python-requests.md) | [Русский](../ru/examples/python-requests.md)
|
||||
|
||||
# Python + requests
|
||||
|
||||
```python
|
||||
import requests
|
||||
|
||||
AUTH = "http://127.0.0.1:5000/v3/auth/tokens"
|
||||
r = requests.post(
|
||||
AUTH,
|
||||
json={
|
||||
"auth": {
|
||||
"identity": {
|
||||
"methods": ["password"],
|
||||
"password": {
|
||||
"user": {
|
||||
"name": "admin",
|
||||
"domain": {"name": "Default"},
|
||||
"password": "secret",
|
||||
}
|
||||
},
|
||||
},
|
||||
"scope": {
|
||||
"project": {"name": "demo", "domain": {"name": "Default"}}
|
||||
},
|
||||
}
|
||||
},
|
||||
)
|
||||
r.raise_for_status()
|
||||
token = r.headers["X-Subject-Token"]
|
||||
headers = {"X-Auth-Token": token}
|
||||
|
||||
servers = requests.get("http://127.0.0.1:8774/v2.1/servers", headers=headers)
|
||||
print(servers.status_code, len(servers.json().get("servers", [])))
|
||||
```
|
||||
@@ -0,0 +1,23 @@
|
||||
**Language / Язык:** [English](terraform.md) | [Русский](../ru/examples/terraform.md)
|
||||
|
||||
# Terraform (openstack provider)
|
||||
|
||||
## Cookbook (single stack)
|
||||
|
||||
[`examples/terraform/main.tf`](../../examples/terraform/main.tf) uses
|
||||
**`terraform-provider-openstack/openstack`** (`openstack_compute_instance_v2`,
|
||||
network, volume attach) against the local gateway ports.
|
||||
|
||||
```bash
|
||||
make up && make seed-demo
|
||||
cd examples/terraform
|
||||
terraform init
|
||||
terraform apply
|
||||
terraform destroy
|
||||
```
|
||||
|
||||
Defaults: `auth_url = http://127.0.0.1:5000/v3`, user `admin`, project `demo`,
|
||||
`insecure = true` (lab HTTP gateway).
|
||||
|
||||
API coverage integration suites now live under [`pulumi-tests/`](../../pulumi-tests/)
|
||||
(Pulumi / `pulumi_openstack`). See [hypervisor-lab.md](../hypervisor-lab.md).
|
||||
@@ -0,0 +1,26 @@
|
||||
**Language / Язык:** [English](troubleshooting-clients.md) | [Русский](../ru/examples/troubleshooting-clients.md)
|
||||
|
||||
# Client troubleshooting
|
||||
|
||||
## Catalog points at unreachable hosts
|
||||
|
||||
The seed catalog uses `host.docker.internal` or compose service hostnames in
|
||||
some setups. Override endpoints or use the gateway host you actually expose
|
||||
(`127.0.0.1` with port-forward).
|
||||
|
||||
## SSL errors against Ingress
|
||||
|
||||
Lab staging issuers are untrusted — use `curl -k` / `OS_INSECURE=true` only in labs.
|
||||
|
||||
## Empty server list
|
||||
|
||||
Wrong project scope, or demo not loaded. Check:
|
||||
|
||||
```bash
|
||||
openstack project list
|
||||
make seed-demo
|
||||
```
|
||||
|
||||
## Microversion rejected
|
||||
|
||||
Lower the requested compute microversion or clear Web UI overrides.
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
**Language / Язык:** [English](faq.md) | [Русский](ru/faq.md)
|
||||
|
||||
# FAQ
|
||||
|
||||
## Is this a real OpenStack cloud?
|
||||
|
||||
No. It is a **surface-complete API laboratory**: PostgreSQL-backed state,
|
||||
API-ref-shaped responses, no hypervisor orchestration.
|
||||
|
||||
## Which release should I use?
|
||||
|
||||
Default **Dalmatian** pack. Switch with `OPENSTACK_SERIES` or the Web UI.
|
||||
See [api-versions.md](api-versions.md).
|
||||
|
||||
## Compose vs Helm?
|
||||
|
||||
| Need | Use |
|
||||
|---|---|
|
||||
| Local hack / CI on Docker | Compose |
|
||||
| Cluster + Ingress TLS | Helm ([kubernetes.md](kubernetes.md)) |
|
||||
|
||||
## Why so many ports?
|
||||
|
||||
OpenStack service catalog expects distinct endpoints. The api-gateway publishes
|
||||
the [real default port matrix](ports.md) **1:1** (no host remapping).
|
||||
|
||||
## Demo cloud wiped my resources
|
||||
|
||||
Lifecycle tests and reseed truncate lab tables. Reload with `make seed-demo`.
|
||||
|
||||
## Can I point Terraform / Ansible at it?
|
||||
|
||||
Yes — use Keystone URL and seeded credentials. Expect lab limitations
|
||||
(policy, async workflows, Ceph, etc.). See [clients.md](clients.md).
|
||||
|
||||
## Where is the Helm chart?
|
||||
|
||||
[`helm/openstack-api-simulator`](../helm/openstack-api-simulator) — guide in
|
||||
[kubernetes.md](kubernetes.md).
|
||||
@@ -0,0 +1,123 @@
|
||||
**Language / Язык:** [English](getting-started.md) | [Русский](ru/getting-started.md)
|
||||
|
||||
# Getting started
|
||||
|
||||
End-to-end first lab session with Docker Compose. For Kubernetes see
|
||||
[kubernetes.md](kubernetes.md).
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Docker / Docker Compose
|
||||
- Python 3.13+ (optional, for host-side smoke scripts)
|
||||
- `curl` or `openstack` CLI / `openstacksdk`
|
||||
|
||||
## Choose a path
|
||||
|
||||
| Path | When |
|
||||
|---|---|
|
||||
| **1a. Published image** | Running lab from Hub image (`docker-compose.release.yml`; needs a repo checkout for gateway/TLS mounts) |
|
||||
| **1b. Development checkout** | You will change code / packs |
|
||||
| **Helm** | Cluster install — [kubernetes.md](kubernetes.md) |
|
||||
|
||||
## 1a. Published image (Docker Hub)
|
||||
|
||||
Requires a **git checkout** of this repo: Compose bind-mounts
|
||||
`./docker/gateway` and `./docker/tls` into the nginx gateway. The simulator
|
||||
container itself comes from Docker Hub (no local app build).
|
||||
|
||||
```bash
|
||||
git clone https://github.com/inecs/openstack-api-simulator.git
|
||||
cd openstack-api-simulator
|
||||
docker compose -f docker-compose.release.yml up -d --wait
|
||||
# or: make release-up
|
||||
```
|
||||
|
||||
Image: [`inecs/openstack-api-simulator`](https://hub.docker.com/r/inecs/openstack-api-simulator).
|
||||
Override tag with `IMAGE_TAG=0.1.0` if needed.
|
||||
|
||||
## 1b. Development checkout
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
docker compose up -d --build --wait
|
||||
```
|
||||
|
||||
## 2. Wait until ready
|
||||
|
||||
```bash
|
||||
curl -sf http://127.0.0.1:5000/health/ready
|
||||
```
|
||||
|
||||
## 3. Seed a profile
|
||||
|
||||
Minimal seed runs on first start. Optional full synthetic cloud:
|
||||
|
||||
```bash
|
||||
make seed-demo
|
||||
# or
|
||||
docker compose exec simulator python -m app.openstack.seed_cli --profile demo
|
||||
```
|
||||
|
||||
Profiles: [seed-profiles.md](seed-profiles.md).
|
||||
|
||||
## 4. Authenticate (Keystone)
|
||||
|
||||
```bash
|
||||
export OS_AUTH_URL=http://127.0.0.1:5000/v3
|
||||
TOKEN=$(curl -si -X POST "$OS_AUTH_URL/auth/tokens" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{
|
||||
"auth": {
|
||||
"identity": {
|
||||
"methods": ["password"],
|
||||
"password": {
|
||||
"user": {
|
||||
"name": "admin",
|
||||
"domain": {"name": "Default"},
|
||||
"password": "secret"
|
||||
}
|
||||
}
|
||||
},
|
||||
"scope": {
|
||||
"project": {"name": "demo", "domain": {"name": "Default"}}
|
||||
}
|
||||
}
|
||||
}' | awk -F': ' 'tolower($1)=="x-subject-token"{print $2}' | tr -d '\r')
|
||||
echo "token=$TOKEN"
|
||||
```
|
||||
|
||||
## 5. Call Nova / Neutron
|
||||
|
||||
```bash
|
||||
curl -sH "X-Auth-Token: $TOKEN" http://127.0.0.1:8774/v2.1/servers/detail | head -c 400
|
||||
curl -sH "X-Auth-Token: $TOKEN" http://127.0.0.1:9696/v2.0/networks
|
||||
```
|
||||
|
||||
## 6. Open the Web UI
|
||||
|
||||
[http://localhost:5000/](http://localhost:5000/) — console, Environment drawer
|
||||
(OpenStack pack series + microversions), Data drawer (load/unload demo cloud).
|
||||
|
||||
## 7. Smoke / conformance
|
||||
|
||||
```bash
|
||||
make smoke
|
||||
python3 examples/python/openstack_smoke.py
|
||||
python3 examples/python/openstack_conformance.py
|
||||
```
|
||||
|
||||
## You're done when…
|
||||
|
||||
- `/health/ready` returns 200
|
||||
- Keystone issues `X-Subject-Token`
|
||||
- Nova/Neutron lists return seeded resources
|
||||
- (optional) demo cloud shows ~1000 servers
|
||||
|
||||
## Next steps
|
||||
|
||||
- [Ports](ports.md) — full service port matrix
|
||||
- [API coverage](api_coverage.md) — pack operations by series
|
||||
- [Clients](clients.md) — openstacksdk / CLI
|
||||
- [Kubernetes / Helm](kubernetes.md)
|
||||
- [Hypervisor-lab](hypervisor-lab.md) — Pulumi API coverage (all ops × series)
|
||||
- [Operations](operations.md)
|
||||
@@ -0,0 +1,33 @@
|
||||
**Language / Язык:** [English](hypervisor-lab.md) | [Русский](ru/hypervisor-lab.md)
|
||||
|
||||
# Pulumi OpenStack coverage lab
|
||||
|
||||
Suite under [`pulumi-tests/`](../pulumi-tests/) that maximises
|
||||
**`pulumi_openstack`**, then HTTP-probes pack operations with **non-empty**
|
||||
response checks across **yoga → dalmatian**.
|
||||
|
||||
## Quick start
|
||||
|
||||
```bash
|
||||
make pulumi-tests # from repo root (full suite)
|
||||
make test-pulumi-smoke # fast collection mode
|
||||
```
|
||||
|
||||
Or:
|
||||
|
||||
```bash
|
||||
cd pulumi-tests
|
||||
make up && make build
|
||||
make test-pulumi
|
||||
open reports/pulumi-report.html
|
||||
```
|
||||
|
||||
## Flow (per series)
|
||||
|
||||
1. Activate series pack
|
||||
2. Pulumi Automation API → `programs/os_coverage` (`pulumi_openstack` resources + data sources)
|
||||
3. Assert every export is non-empty
|
||||
4. HTTP probe remaining/all pack ops; require non-empty bodies on successful GET/POST
|
||||
5. Destroy stack; emit HTML + JUnit
|
||||
|
||||
See [`pulumi-tests/README.md`](../pulumi-tests/README.md).
|
||||
@@ -0,0 +1,184 @@
|
||||
**Language / Язык:** [English](kubernetes.md) | [Русский](ru/kubernetes.md)
|
||||
|
||||
# Kubernetes / Helm
|
||||
|
||||
Deploy the published Docker Hub runtime image with the chart in
|
||||
[`helm/openstack-api-simulator`](../helm/openstack-api-simulator).
|
||||
|
||||
Image: [`inecs/openstack-api-simulator`](https://hub.docker.com/r/inecs/openstack-api-simulator)
|
||||
|
||||
The chart mirrors Docker Compose:
|
||||
|
||||
| Component | Role |
|
||||
|---|---|
|
||||
| **simulator** Deployment | FastAPI app on `:8080` |
|
||||
| **api-gateway** Deployment | nginx multi-port OpenStack gateway |
|
||||
| **PostgreSQL** StatefulSet | Bundled Postgres 17 (optional) |
|
||||
| **migrate** initContainer | Idempotent schema migrations |
|
||||
| **seed** Job (optional) | `minimal` or `demo` lab data |
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Kubernetes 1.27+ (or comparable)
|
||||
- Helm 3.14+
|
||||
- For Ingress TLS: [Ingress NGINX](https://kubernetes.github.io/ingress-nginx/) and
|
||||
[cert-manager](https://cert-manager.io/)
|
||||
|
||||
Example cert-manager install:
|
||||
|
||||
```bash
|
||||
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.17.2/cert-manager.yaml
|
||||
```
|
||||
|
||||
## Quick install (Hub release + Ingress + Let's Encrypt)
|
||||
|
||||
From a git checkout of this repository:
|
||||
|
||||
```bash
|
||||
helm upgrade --install os-sim ./helm/openstack-api-simulator \
|
||||
-n openstack-sim --create-namespace \
|
||||
-f ./helm/openstack-api-simulator/values-ingress-example.yaml \
|
||||
--set certManager.email=you@example.com \
|
||||
--set ingress.hosts[0].host=os-sim.example.com \
|
||||
--set ingress.tls[0].hosts[0]=os-sim.example.com \
|
||||
--set secret.ticketSigningKey="$(openssl rand -hex 32)" \
|
||||
--set postgresql.auth.password="$(openssl rand -hex 16)"
|
||||
```
|
||||
|
||||
What this does:
|
||||
|
||||
1. Pulls `inecs/openstack-api-simulator:0.1.0`.
|
||||
2. Installs bundled PostgreSQL 17 (`postgres:17.5-bookworm`).
|
||||
3. Runs schema migrations in an init container (idempotent).
|
||||
4. Seeds the **demo** lab profile (`seed.enabled=true`, ~1000 servers).
|
||||
5. Deploys nginx **api-gateway** with OpenStack default ports (5000, 8774, 9696, …).
|
||||
6. Creates `ClusterIssuer` resources (`letsencrypt-prod` / `letsencrypt-staging`).
|
||||
7. Creates an Ingress → gateway `:5000` (Keystone + Web UI) with TLS.
|
||||
|
||||
DNS for `os-sim.example.com` must point at your Ingress controller. Then:
|
||||
|
||||
```bash
|
||||
kubectl -n openstack-sim get certificate,ingress,pods
|
||||
curl -sS https://os-sim.example.com/health/ready
|
||||
open https://os-sim.example.com/
|
||||
```
|
||||
|
||||
Default seeded login: `admin` / `secret` (project `demo` or `admin`, domain `Default`).
|
||||
|
||||
### Staging first (recommended)
|
||||
|
||||
```bash
|
||||
helm upgrade --install os-sim ./helm/openstack-api-simulator \
|
||||
-n openstack-sim --create-namespace \
|
||||
-f ./helm/openstack-api-simulator/values-ingress-example.yaml \
|
||||
--set certManager.email=you@example.com \
|
||||
--set certManager.useStaging=true \
|
||||
--set ingress.hosts[0].host=os-sim.example.com \
|
||||
--set ingress.tls[0].hosts[0]=os-sim.example.com \
|
||||
--set secret.ticketSigningKey="$(openssl rand -hex 32)"
|
||||
```
|
||||
|
||||
Use `curl -k` against the staging CA. Flip `certManager.useStaging=false` for production.
|
||||
|
||||
## Minimal install (ClusterIP + port-forward)
|
||||
|
||||
```bash
|
||||
helm upgrade --install os-sim ./helm/openstack-api-simulator \
|
||||
-n openstack-sim --create-namespace \
|
||||
--set secret.ticketSigningKey="$(openssl rand -hex 32)" \
|
||||
--set seed.enabled=true \
|
||||
--set seed.profile=minimal
|
||||
|
||||
kubectl -n openstack-sim port-forward \
|
||||
svc/os-sim-openstack-api-simulator-gateway \
|
||||
5000:5000 8774:8774 9696:9696 9292:9292 8776:8776
|
||||
```
|
||||
|
||||
| URL | Service |
|
||||
|---|---|
|
||||
| http://127.0.0.1:5000/ | Keystone + console |
|
||||
| http://127.0.0.1:8774/v2.1/ | Nova |
|
||||
| http://127.0.0.1:9696/v2.0/ | Neutron |
|
||||
|
||||
Full port matrix: [ports.md](ports.md).
|
||||
|
||||
## External PostgreSQL
|
||||
|
||||
```bash
|
||||
helm upgrade --install os-sim ./helm/openstack-api-simulator \
|
||||
-n openstack-sim --create-namespace \
|
||||
--set postgresql.enabled=false \
|
||||
--set secret.ticketSigningKey="$(openssl rand -hex 32)" \
|
||||
--set secret.databaseUrl='postgresql://user:pass@pg.example.com:5432/openstack_simulator'
|
||||
```
|
||||
|
||||
Or use `secret.existingSecret` with keys `DATABASE_URL` and `TICKET_SIGNING_KEY`.
|
||||
|
||||
## How the api-gateway works
|
||||
|
||||
Same model as Compose (`docker/gateway/openstack-ports.conf`):
|
||||
|
||||
1. Client connects to a **service-specific port** (e.g. Nova `8774`).
|
||||
2. nginx sets `X-OpenStack-Service` and `X-Forwarded-Port`.
|
||||
3. FastAPI rewrites to `/_os/<service>/…` so `/v3` (Keystone vs Cinder) does not collide.
|
||||
|
||||
Ingress (when enabled) fronts **Keystone/UI on port 5000**. For Nova/Neutron from
|
||||
outside the cluster, either:
|
||||
|
||||
- `kubectl port-forward` additional ports, or
|
||||
- expose `*-gateway` as `LoadBalancer` / `NodePort` (`gateway.service.type`), or
|
||||
- add extra Ingress rules / TCP services for those ports.
|
||||
|
||||
## How TLS issuance works
|
||||
|
||||
When `certManager.enabled=true` and `certManager.createClusterIssuer=true`, the
|
||||
chart creates ACME `ClusterIssuer` objects (HTTP-01). The Ingress template adds:
|
||||
|
||||
```yaml
|
||||
metadata:
|
||||
annotations:
|
||||
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||
spec:
|
||||
tls:
|
||||
- secretName: openstack-api-simulator-tls
|
||||
hosts: [os-sim.example.com]
|
||||
```
|
||||
|
||||
The chart does **not** install cert-manager or the Ingress controller.
|
||||
|
||||
## Operations
|
||||
|
||||
```bash
|
||||
# logs
|
||||
kubectl -n openstack-sim logs -l app.kubernetes.io/component=simulator -f
|
||||
kubectl -n openstack-sim logs -l app.kubernetes.io/component=gateway -f
|
||||
|
||||
# reseed minimal
|
||||
kubectl -n openstack-sim exec deploy/os-sim-openstack-api-simulator -- \
|
||||
python -m app.openstack.seed_cli --profile minimal
|
||||
|
||||
# reseed demo cloud
|
||||
kubectl -n openstack-sim exec deploy/os-sim-openstack-api-simulator -- \
|
||||
python -m app.openstack.seed_cli --profile demo
|
||||
|
||||
# activate OpenStack pack series
|
||||
kubectl -n openstack-sim set env deploy/os-sim-openstack-api-simulator \
|
||||
OPENSTACK_SERIES=caracal
|
||||
# then restart the pod / helm upgrade with --set config.openstackSeries=caracal
|
||||
|
||||
# uninstall
|
||||
helm -n openstack-sim uninstall os-sim
|
||||
```
|
||||
|
||||
## Values reference
|
||||
|
||||
See [`helm/openstack-api-simulator/values.yaml`](../helm/openstack-api-simulator/values.yaml)
|
||||
and the [chart README](../helm/openstack-api-simulator/README.md).
|
||||
|
||||
Related docs:
|
||||
|
||||
- [Getting started](getting-started.md) — Compose path
|
||||
- [Operations](operations.md) — Docker Hub publish / day-2
|
||||
- [Ports](ports.md) — OpenStack port matrix
|
||||
- [Seed profiles](seed-profiles.md) — `minimal` / `demo`
|
||||
- [Security](security.md) — lab credentials
|
||||
@@ -0,0 +1,39 @@
|
||||
**Language / Язык:** [English](observability.md) | [Русский](ru/observability.md)
|
||||
|
||||
# Observability
|
||||
|
||||
## Health endpoints
|
||||
|
||||
| Path | Meaning |
|
||||
|---|---|
|
||||
| `/health/live` | Process is running |
|
||||
| `/health/ready` | DB reachable + migrations applied |
|
||||
|
||||
Both are exposed on the simulator and via the gateway (any published port).
|
||||
|
||||
## Request IDs
|
||||
|
||||
Header `X-Request-ID` (configurable via `REQUEST_ID_HEADER`) is accepted and
|
||||
echoed where middleware applies.
|
||||
|
||||
## Logs
|
||||
|
||||
Compose:
|
||||
|
||||
```bash
|
||||
make logs
|
||||
docker compose logs -f simulator api-gateway
|
||||
```
|
||||
|
||||
Helm:
|
||||
|
||||
```bash
|
||||
kubectl logs -l app.kubernetes.io/component=simulator -f
|
||||
kubectl logs -l app.kubernetes.io/component=gateway -f
|
||||
```
|
||||
|
||||
## Compatibility / coverage evidence
|
||||
|
||||
- Pack coverage: [api_coverage.md](api_coverage.md)
|
||||
- Live lifecycle: `examples/python/openstack_surface_probe.py`
|
||||
- pytest: `tests/openstack/` (includes real-DB conformance)
|
||||
@@ -0,0 +1,117 @@
|
||||
**Language / Язык:** [English](operations.md) | [Русский](ru/operations.md)
|
||||
|
||||
# Operations
|
||||
|
||||
## Day-2 commands (Compose)
|
||||
|
||||
```bash
|
||||
make up # start stack
|
||||
make down # stop stack
|
||||
make restart
|
||||
make logs
|
||||
make db-migrate # idempotent migrations
|
||||
make seed # minimal OpenStack seed
|
||||
make seed-demo # demo cloud (~1000 servers)
|
||||
make smoke # multi-service GET smoke
|
||||
```
|
||||
|
||||
## Migrations
|
||||
|
||||
Ordered SQL under `app/db/migrations/` applies transactionally.
|
||||
Re-running `make db-migrate` is safe. `/health/ready` stays unavailable until
|
||||
migrations are applied. Helm runs the same migrate step as an initContainer.
|
||||
|
||||
## Reseed
|
||||
|
||||
```bash
|
||||
make seed # minimal
|
||||
make seed-demo # replaces state with demo cloud
|
||||
```
|
||||
|
||||
Or:
|
||||
|
||||
```bash
|
||||
docker compose exec simulator python -m app.openstack.seed_cli --profile demo
|
||||
```
|
||||
|
||||
Reseed **truncates** OpenStack lab tables and reloads. External automation that
|
||||
cached resource UUIDs must refresh.
|
||||
|
||||
## OpenStack pack series
|
||||
|
||||
Cold start (env):
|
||||
|
||||
```bash
|
||||
OPENSTACK_SERIES=caracal docker compose up -d
|
||||
```
|
||||
|
||||
Helm:
|
||||
|
||||
```bash
|
||||
--set config.openstackSeries=yoga
|
||||
```
|
||||
|
||||
Hot-swap (Web UI or API):
|
||||
|
||||
```bash
|
||||
curl -X POST http://127.0.0.1:5000/ui/api/openstack/contracts/activate \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"series":"dalmatian"}'
|
||||
```
|
||||
|
||||
Series: `yoga`, `antelope`, `caracal`, `dalmatian`. Coverage:
|
||||
[api_coverage.md](api_coverage.md).
|
||||
|
||||
## Regenerating contract packs
|
||||
|
||||
```bash
|
||||
PYTHONPATH=tools python3 tools/os_api_inventory/generate_packs.py
|
||||
PYTHONPATH=tools python3 tools/os_api_inventory/coverage_report.py
|
||||
```
|
||||
|
||||
## Backing up lab state
|
||||
|
||||
PostgreSQL is the system of record. Use `pg_dump` / volume snapshots.
|
||||
Application containers are disposable when the database volume remains.
|
||||
|
||||
## Publishing to Docker Hub
|
||||
|
||||
```bash
|
||||
docker login
|
||||
make release
|
||||
```
|
||||
|
||||
| Variable | Default | Meaning |
|
||||
|---|---|---|
|
||||
| `DOCKERHUB_USER` | `inecs` | Docker Hub namespace |
|
||||
| `IMAGE_NAME` | `openstack-api-simulator` | Repository name |
|
||||
| `VERSION` | from `pyproject.toml` | Image tag |
|
||||
|
||||
```bash
|
||||
make release VERSION=0.2.0
|
||||
make release-build # local tags only
|
||||
```
|
||||
|
||||
## Kubernetes day-2
|
||||
|
||||
See [kubernetes.md](kubernetes.md) for logs, reseed via `kubectl exec`, and
|
||||
uninstall.
|
||||
|
||||
## API coverage lab CI (pulumi-tests)
|
||||
|
||||
Pulumi probes every pack operation across series — see
|
||||
[hypervisor-lab.md](hypervisor-lab.md).
|
||||
|
||||
```bash
|
||||
make test-pulumi-smoke # from repo root
|
||||
make test-pulumi
|
||||
```
|
||||
|
||||
Reports: `pulumi-tests/reports/pulumi-report.html` and `pulumi-junit.xml`.
|
||||
|
||||
## Upgrades
|
||||
|
||||
1. Pull / build new image tag.
|
||||
2. Apply migrations (automatic on start / Helm initContainer).
|
||||
3. Optionally reseed if the seed schema changed.
|
||||
4. Re-run `make smoke` or lifecycle probes.
|
||||
@@ -0,0 +1,56 @@
|
||||
**Language / Язык:** [English](ports.md) | [Русский](ru/ports.md)
|
||||
|
||||
# OpenStack default ports in this simulator
|
||||
|
||||
Reference: [Firewalls and default ports](https://docs.openstack.org/install-guide/firewalls-default-ports.html).
|
||||
|
||||
These are the **real OpenStack public API defaults**. Compose and Helm publish
|
||||
them **1:1** on the host / Service (no remapping): host `5000` is Keystone,
|
||||
host `8774` is Nova, and so on. Run this stack on its own host/VM so these
|
||||
ports do not collide with other lab simulators.
|
||||
|
||||
Clients talk to **api-gateway** (nginx) — Compose service or Helm
|
||||
`*-gateway` Deployment/Service. Each listen port sets `X-OpenStack-Service`
|
||||
and `X-Forwarded-Port`; the FastAPI process rewrites the path to
|
||||
`/_os/<service>/…` so overlapping API roots (`/v3`, `/v1`, …) do not collide.
|
||||
|
||||
Typical auth URL: `http://127.0.0.1:5000/v3` (or HTTPS on `:5000` / `:443`
|
||||
via the gateway).
|
||||
|
||||
Helm values list: `gateway.service.ports` in
|
||||
[`helm/openstack-api-simulator/values.yaml`](../helm/openstack-api-simulator/values.yaml).
|
||||
|
||||
| Port | Service | Role | Primary paths |
|
||||
|------|---------|------|---------------|
|
||||
| 5000 | keystone | Identity — tokens, projects, users, roles, service catalog | `/v3/auth/tokens`, `/v3/projects`, … |
|
||||
| 8774 | nova | Compute — servers (VMs), flavors, keypairs, AZ, hypervisors | `/v2.1/servers`, flavors, keypairs, AZ, hypervisors, … |
|
||||
| 9696 | neutron | Network — networks, subnets, ports, routers, SG, floating IPs | `/v2.0/networks`, subnets, ports, routers, SG, FIPs, QoS, trunks, … |
|
||||
| 9292 | glance | Image — glance images | `/v2/images` |
|
||||
| 8776 | cinder | Block storage — volumes, snapshots, volume types | `/v3/volumes` |
|
||||
| 8003 | placement | Placement — resource providers and inventories | `/resource_providers` |
|
||||
| 8004 | heat | Orchestration — Heat stacks | `/v1/{project_id}/stacks` |
|
||||
| 8000 | heat-cfn | CloudFormation-compatible Heat API | `/stacks` |
|
||||
| 8080 | swift | Object storage — accounts, containers, objects | `/v1/{account}/{container}/…`, `/info` |
|
||||
| 6385 | ironic | Bare metal — nodes, ports, chassis | `/v1/nodes` |
|
||||
| 9876 | octavia | Load balancing — load balancers, listeners, pools | `/v2/lbaas/loadbalancers` |
|
||||
| 9311 | barbican | Key manager — secrets, containers | `/v1/secrets` |
|
||||
| 8786 | manila | Shared file systems — shares | `/v2/shares` |
|
||||
| 9001 | designate | DNS — zones and recordsets | `/v2/zones` |
|
||||
| 9511 | magnum | Container infra — clusters (e.g. Kubernetes) | `/v1/clusters` |
|
||||
| 9517 | zun | Containers — container lifecycle | `/v1/containers` |
|
||||
| 8779 | trove | Database as a service — DB instances | `/v1.0/instances` |
|
||||
| 8989 | mistral | Workflows | `/v2/workflows` |
|
||||
| 8042 | aodh | Alarming | `/v2/alarms` |
|
||||
| 8889 | cloudkitty | Rating / billing metering | `/v1/rating/…` |
|
||||
| 9090 | freezer | Backup jobs | `/v2/jobs` |
|
||||
| 1234 | blazar | Reservation — leases | `/leases` |
|
||||
| 8999 | vitrage | Root cause analysis (RCA) | `/v1/alarm` |
|
||||
| 15868 | masakari | Instance high availability | `/v1/segments` |
|
||||
| 9890 | tacker | NFV orchestration | `/v1.0/vnfs` |
|
||||
| 5050 | adjutant | Admin workflows / self-service tasks | `/v1/tasks` |
|
||||
| 9322 | watcher | Infrastructure optimization | `/v1/…` |
|
||||
| 8888 | zaqar | Messaging | `/v2/…` |
|
||||
| 80 | http | Console UI reverse proxy (Compose + Helm gateway) | — |
|
||||
| 443 | https | TLS reverse proxy (**Compose only**; Helm terminates TLS at Ingress) | — |
|
||||
|
||||
Internal FastAPI listens on `8080` inside Docker only (not the Swift public port from the host — host `8080` is Swift via gateway). Postgres is published only as `127.0.0.1:5433` (not an OpenStack API port).
|
||||
@@ -0,0 +1,35 @@
|
||||
**Language / Язык:** [English](../README.md) | [Русский](README.md)
|
||||
|
||||
# Документация
|
||||
|
||||
Руководства по лабораторному симулятору OpenStack API. Переключайте язык
|
||||
заголовком на каждой странице. Английские оригиналы — в родительском
|
||||
каталоге [`docs/`](../README.md).
|
||||
|
||||
| Руководство | Тема |
|
||||
|---|---|
|
||||
| [Быстрый старт](getting-started.md) | Первая лабораторная сессия (Compose) |
|
||||
| [Kubernetes / Helm](kubernetes.md) | Установка в кластер, Ingress, cert-manager |
|
||||
| [Конфигурация](configuration.md) | Переменные окружения, Compose, Helm |
|
||||
| [Аутентификация](authentication.md) | Токены Keystone и seed-пользователи |
|
||||
| [Порты](ports.md) | Реальные порты API OpenStack (публикация 1:1) |
|
||||
| [API surface](api-surface.md) | Специализированные vs schema-пакеты |
|
||||
| [Версии API](api-versions.md) | Серии Yoga → Dalmatian |
|
||||
| [Покрытие API](api_coverage.md) | Счётчики операций |
|
||||
| [Seed-профили](seed-profiles.md) | `minimal` / `demo` |
|
||||
| [Клиенты](clients.md) | SDK / CLI |
|
||||
| [Web UI](web-ui.md) | Консоль и drawers |
|
||||
| [Эксплуатация](operations.md) | Day-2, релиз, reseed |
|
||||
| [Архитектура](architecture.md) | Компоненты и путь запроса |
|
||||
| [Безопасность](security.md) | Threat model лаборатории |
|
||||
| [Наблюдаемость](observability.md) | Health и логи |
|
||||
| [Устранение неполадок](troubleshooting.md) | Типичные сбои |
|
||||
| [FAQ](faq.md) | Краткие ответы |
|
||||
| [Домены](domains/README.md) | Заметки по сервисам |
|
||||
| [Примеры](examples/overview.md) | Cookbook'и клиентов |
|
||||
| [Hypervisor-lab](hypervisor-lab.md) | Pulumi-покрытие API (все ops × серии) |
|
||||
|
||||
Исполняемые cookbook'и: [`examples/`](../../examples/README.ru.md).
|
||||
Интеграционные сьюты: [`pulumi-tests/`](../../pulumi-tests/README.ru.md).
|
||||
|
||||
Назад к [README](../../README.ru.md).
|
||||
@@ -0,0 +1,44 @@
|
||||
**Language / Язык:** [English](../api-surface.md) | [Русский](api-surface.md)
|
||||
|
||||
# Поверхность API
|
||||
|
||||
## Surface-complete пакеты
|
||||
|
||||
Каждый пакет серии OpenStack перечисляет операции **method + path**. При старте
|
||||
каждая уникальная пара `(method, path)` регистрируется как отдельный маршрут FastAPI
|
||||
(`os-contract:…`), в стиле Proxmox. Stateful-обработчики из специализированных
|
||||
модулей ищутся через `HandlerRegistry`; всё остальное уходит в schema-движок
|
||||
(лабораторный JSON `os_api_objects`).
|
||||
|
||||
| Series | Services | Operations (approx.) |
|
||||
|---|---|---|
|
||||
| Yoga | 28 | ~1060 |
|
||||
| Antelope | 28 | ~1108 |
|
||||
| Caracal | 28 | ~1196 |
|
||||
| Dalmatian | 28 | ~1357 |
|
||||
|
||||
Авторитетные числа: [api_coverage.md](api_coverage.md).
|
||||
|
||||
## Handlers vs schema fallback
|
||||
|
||||
| Слой | Сервисы / ресурсы |
|
||||
|---|---|
|
||||
| **Специализированные handlers** | Keystone tokens/catalog, Nova servers/flavors/keypairs/…, Neutron nets/ports/…, Glance images, Cinder volumes, Heat stacks, Swift, Ironic nodes, Octavia LBs, Placement RPs |
|
||||
| **Schema fallback** | Остальные коллекции пакета (Barbican, Manila, Designate, Magnum, …), включая вложенные пути |
|
||||
|
||||
## Microversions
|
||||
|
||||
Заголовки вроде `OpenStack-API-Version: compute 2.79` и
|
||||
`X-OpenStack-Nova-API-Version` принимаются и фильтруются по метаданным пакета.
|
||||
Переопределения можно задать в Web UI Environment drawer.
|
||||
|
||||
## Actions
|
||||
|
||||
Nova-style `POST /servers/{id}/action` и аналогичные ops пакета `kind=action`
|
||||
обрабатываются schema/action-путём (обновление power state для типичных actions).
|
||||
|
||||
## Ошибки
|
||||
|
||||
Ошибки в форме OpenStack (`OpenStackError`) с `code`, `title`, `message`.
|
||||
Неизвестные маршруты, отсутствующие в активном contract-пакете, возвращают
|
||||
стандартный FastAPI `404`.
|
||||
@@ -0,0 +1,56 @@
|
||||
**Language / Язык:** [English](../api-versions.md) | [Русский](api-versions.md)
|
||||
|
||||
# Версии API (series packs)
|
||||
|
||||
Симулятор поставляет **четыре** серии релизов OpenStack как contract-пакеты:
|
||||
|
||||
| Series | OpenStack release family | Cold-start env |
|
||||
|---|---|---|
|
||||
| `yoga` | Yoga | `OPENSTACK_SERIES=yoga` |
|
||||
| `antelope` | Antelope | `OPENSTACK_SERIES=antelope` |
|
||||
| `caracal` | Caracal | `OPENSTACK_SERIES=caracal` |
|
||||
| `dalmatian` | Dalmatian (default) | `OPENSTACK_SERIES=dalmatian` |
|
||||
|
||||
## Cold start
|
||||
|
||||
Compose / процесс:
|
||||
|
||||
```bash
|
||||
OPENSTACK_SERIES=caracal docker compose up -d
|
||||
```
|
||||
|
||||
Helm:
|
||||
|
||||
```bash
|
||||
--set config.openstackSeries=yoga
|
||||
```
|
||||
|
||||
## Hot-swap
|
||||
|
||||
```bash
|
||||
curl -X POST http://127.0.0.1:5000/ui/api/openstack/contracts/activate \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"series":"dalmatian"}'
|
||||
```
|
||||
|
||||
Или Web UI → Environment → OpenStack API pack → Activate.
|
||||
|
||||
Hot-swap перемонтирует schema-маршруты (`remount_schema_services`) без пересборки
|
||||
образа.
|
||||
|
||||
## Структура пакета
|
||||
|
||||
```
|
||||
contracts/openstack/<series>/
|
||||
manifest.json
|
||||
keystone/api.json
|
||||
nova/api.json
|
||||
neutron/api.json
|
||||
…
|
||||
```
|
||||
|
||||
Перегенерация:
|
||||
|
||||
```bash
|
||||
PYTHONPATH=tools python3 tools/os_api_inventory/generate_packs.py
|
||||
```
|
||||
@@ -0,0 +1,64 @@
|
||||
**Language / Язык:** [English](../api_coverage.md) | [Русский](api_coverage.md)
|
||||
|
||||
# Покрытие OpenStack API — dalmatian
|
||||
|
||||
Сгенерировано из `contracts/openstack/dalmatian/manifest.json`.
|
||||
|
||||
- **Services:** 28
|
||||
- **Operations:** 1357
|
||||
- **Checksum:** `5d8f32baa835db2b556b6f33ac3c1b67b74db8194f00ce7d6eb8c59e3bbd7063`
|
||||
- **Generated at:** 2026-07-16T00:28:30Z
|
||||
|
||||
## Дельты серий
|
||||
|
||||
| Series | Major | Operations |
|
||||
|---|---:|---:|
|
||||
| Antelope | 7 | 1108 |
|
||||
| Caracal | 8 | 1196 |
|
||||
| Dalmatian | 9 | 1357 |
|
||||
| Yoga | 6 | 1060 |
|
||||
|
||||
Более старые серии опускают пути, добавленные позже (`tools/os_api_inventory/series_deltas.py`),
|
||||
и используют более низкие потолки microversion. Примените пакет в Environment drawer для hot-swap.
|
||||
|
||||
Surface-complete означает, что каждая операция пакета смонтирована schema-движком
|
||||
(специализированные роутеры по-прежнему выигрывают на пересекающихся stateful-путях).
|
||||
|
||||
| Service | Type | Port | Operations | Microversions |
|
||||
|---|---|---:|---:|---|
|
||||
| adjutant | admin-logic | 5050 | 24 | — |
|
||||
| aodh | alarming | 8042 | 19 | — |
|
||||
| barbican | key-manager | 9311 | 25 | — |
|
||||
| blazar | reservation | 1234 | 19 | — |
|
||||
| cinder | volumev3 | 8776 | 98 | 3.0–3.70 |
|
||||
| cloudkitty | rating | 8889 | 25 | — |
|
||||
| designate | dns | 9001 | 37 | — |
|
||||
| freezer | backup | 9090 | 31 | — |
|
||||
| glance | image | 9292 | 39 | — |
|
||||
| heat | orchestration | 8004 | 38 | — |
|
||||
| heat-cfn | cloudformation | 8000 | 8 | — |
|
||||
| ironic | baremetal | 6385 | 58 | 1.1–1.90 |
|
||||
| keystone | identity | 5000 | 77 | — |
|
||||
| magnum | container-infra | 9511 | 25 | — |
|
||||
| manila | sharev2 | 8786 | 50 | 2.0–2.82 |
|
||||
| masakari | instance-ha | 15868 | 19 | — |
|
||||
| mistral | workflowv2 | 8989 | 37 | — |
|
||||
| neutron | network | 9696 | 290 | — |
|
||||
| nova | compute | 8774 | 124 | 2.1–2.96 |
|
||||
| octavia | load-balancer | 9876 | 74 | — |
|
||||
| placement | placement | 8003 | 30 | 1.0–1.39 |
|
||||
| swift | object-store | 8080 | 10 | — |
|
||||
| tacker | nfv-orchestration | 9890 | 30 | — |
|
||||
| trove | database | 8779 | 31 | — |
|
||||
| vitrage | rca | 8999 | 30 | — |
|
||||
| watcher | infra-optim | 9322 | 49 | — |
|
||||
| zaqar | messaging | 8888 | 27 | — |
|
||||
| zun | container | 9517 | 33 | — |
|
||||
|
||||
## Минимумы core
|
||||
|
||||
| Service | Required | Actual |
|
||||
|---|---:|---:|
|
||||
| keystone | 40 | 77 (OK) |
|
||||
| neutron | 70 | 290 (OK) |
|
||||
| nova | 70 | 124 (OK) |
|
||||
@@ -0,0 +1,58 @@
|
||||
**Language / Язык:** [English](../architecture.md) | [Русский](architecture.md)
|
||||
|
||||
# Архитектура
|
||||
|
||||
## Компоненты
|
||||
|
||||
```
|
||||
┌─────────────┐ ┌──────────────────┐ ┌────────────┐
|
||||
│ Clients │────▶│ api-gateway │────▶│ simulator │
|
||||
│ SDK / CLI │ │ nginx multi-port│ │ FastAPI │
|
||||
│ Web UI │ │ :5000,:8774,… │ │ :8080 │
|
||||
└─────────────┘ └──────────────────┘ └─────┬──────┘
|
||||
│
|
||||
┌─────▼──────┐
|
||||
│ PostgreSQL │
|
||||
└────────────┘
|
||||
```
|
||||
|
||||
| Компонент | Ответственность |
|
||||
|---|---|
|
||||
| **api-gateway** | Публикация стандартных портов OpenStack; выставление `X-OpenStack-Service` / `X-Forwarded-Port` |
|
||||
| **ServiceDispatchMiddleware** | Переписывание в `/_os/<service>/…` |
|
||||
| **Специализированные роутеры** | Stateful Keystone, Nova, Neutron, Glance, Cinder, Heat, Swift, Ironic, Octavia, Placement |
|
||||
| **Schema engine** | Surface-complete ops из `contracts/openstack/<series>/` |
|
||||
| **PostgreSQL** | Identity, IaaS-таблицы, generic store `os_api_objects` |
|
||||
|
||||
## Жизненный цикл запроса
|
||||
|
||||
1. Клиент обращается, например, к `http://host:8774/v2.1/servers`.
|
||||
2. Gateway добавляет service headers.
|
||||
3. Dispatch монтирует запрос под `/_os/nova/…`.
|
||||
4. Выполняется специализированный Nova handler **или** schema pack operation.
|
||||
5. Чтение/запись идут в PostgreSQL (типизированные таблицы или `os_api_objects`).
|
||||
|
||||
## Contract-пакеты
|
||||
|
||||
- Сгенерированный inventory → `contracts/openstack/{yoga,antelope,caracal,dalmatian}/`
|
||||
- Hot-swap через Web UI / `/ui/api/openstack/contracts/activate`
|
||||
- Отчёт покрытия: [api_coverage.md](api_coverage.md)
|
||||
|
||||
## Seed-профили
|
||||
|
||||
| Profile | Содержимое |
|
||||
|---|---|
|
||||
| `minimal` | Небольшой Keystone + несколько IaaS-ресурсов |
|
||||
| `demo` | ~1000 servers, multi-project topology, nested collections |
|
||||
|
||||
Подробности: [seed-profiles.md](seed-profiles.md).
|
||||
|
||||
## Модель развёртывания
|
||||
|
||||
| Mode | Gateway | DB |
|
||||
|---|---|---|
|
||||
| Compose | nginx container | bundled Postgres |
|
||||
| Helm | nginx Deployment + multi-port Service | bundled StatefulSet или external |
|
||||
| Ingress | TLS terminates at Ingress → gateway:5000 | — |
|
||||
|
||||
См. [kubernetes.md](kubernetes.md).
|
||||
@@ -0,0 +1,80 @@
|
||||
**Language / Язык:** [English](../authentication.md) | [Русский](authentication.md)
|
||||
|
||||
# Аутентификация
|
||||
|
||||
Симулятор реализует **Keystone v3** password-аутентификацию и project scoping
|
||||
(лабораторное подмножество).
|
||||
|
||||
## Password auth
|
||||
|
||||
```http
|
||||
POST /v3/auth/tokens
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"auth": {
|
||||
"identity": {
|
||||
"methods": ["password"],
|
||||
"password": {
|
||||
"user": {
|
||||
"name": "admin",
|
||||
"domain": {"name": "Default"},
|
||||
"password": "secret"
|
||||
}
|
||||
}
|
||||
},
|
||||
"scope": {
|
||||
"project": {"name": "demo", "domain": {"name": "Default"}}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Ответ:
|
||||
|
||||
- Заголовок **`X-Subject-Token`** — используйте как **`X-Auth-Token`** в следующих запросах
|
||||
- Тело `token.catalog` — endpoints сервисов (порты соответствуют [ports.md](ports.md))
|
||||
|
||||
## Seed-принципалы
|
||||
|
||||
Пароль для всех пользователей: **`secret`**. Домен: **`Default`**.
|
||||
|
||||
### Minimal seed
|
||||
|
||||
| Пользователь | Проекты | Роль |
|
||||
|---|---|---|
|
||||
| `admin` | `admin`, `demo` | admin |
|
||||
| `demo` | `demo` | member |
|
||||
|
||||
### Demo cloud
|
||||
|
||||
| Пользователь | Типичные проекты |
|
||||
|---|---|
|
||||
| `admin` | все |
|
||||
| `ops` | production, staging |
|
||||
| `developer` | development, staging |
|
||||
| `demo` / `auditor` | demo / production |
|
||||
|
||||
## Unscoped / ошибки
|
||||
|
||||
- Нет токена → `401 Unauthorized`
|
||||
- Неверный пароль → `401`
|
||||
- Project-scoped API без project scope → `401` с понятным сообщением
|
||||
|
||||
## openstacksdk / CLI
|
||||
|
||||
```bash
|
||||
export OS_AUTH_URL=http://127.0.0.1:5000/v3
|
||||
export OS_USERNAME=admin
|
||||
export OS_PASSWORD=secret
|
||||
export OS_PROJECT_NAME=demo
|
||||
export OS_USER_DOMAIN_NAME=Default
|
||||
export OS_PROJECT_DOMAIN_NAME=Default
|
||||
export OS_IDENTITY_API_VERSION=3
|
||||
|
||||
openstack server list
|
||||
openstack network list
|
||||
```
|
||||
|
||||
Против Helm Ingress задайте `OS_AUTH_URL=https://os-sim.example.com/v3`
|
||||
(и доверьте сертификат или используйте `--insecure` в лаборатории).
|
||||
@@ -0,0 +1,46 @@
|
||||
**Language / Язык:** [English](../clients.md) | [Русский](clients.md)
|
||||
|
||||
# Клиенты
|
||||
|
||||
## Матрица подключения
|
||||
|
||||
| Client | Auth URL | Примечания |
|
||||
|---|---|---|
|
||||
| curl | `http://127.0.0.1:5000/v3` | Используйте `X-Subject-Token` → `X-Auth-Token` |
|
||||
| openstack CLI | `OS_AUTH_URL=…/v3` | См. [authentication.md](authentication.md) |
|
||||
| openstacksdk | same | Порты service catalog должны совпадать с gateway |
|
||||
| Terraform OpenStack provider | `auth_url` | Укажите Keystone; catalog направляет Nova/Neutron |
|
||||
| Ansible `openstack.*` | clouds.yaml | Те же credentials, что и для CLI |
|
||||
|
||||
## Compose (локально)
|
||||
|
||||
```bash
|
||||
export OS_AUTH_URL=http://127.0.0.1:5000/v3
|
||||
export OS_USERNAME=admin
|
||||
export OS_PASSWORD=secret
|
||||
export OS_PROJECT_NAME=demo
|
||||
export OS_USER_DOMAIN_NAME=Default
|
||||
export OS_PROJECT_DOMAIN_NAME=Default
|
||||
export OS_IDENTITY_API_VERSION=3
|
||||
```
|
||||
|
||||
## Helm / Ingress
|
||||
|
||||
```bash
|
||||
export OS_AUTH_URL=https://os-sim.example.com/v3
|
||||
# Другие сервисы: port-forward портов gateway или catalog URLs,
|
||||
# которые ваш Ingress/DNS корректно мапят.
|
||||
```
|
||||
|
||||
Для multi-port доступа без Ingress TCP используйте port-forward gateway Service
|
||||
(см. [kubernetes.md](kubernetes.md)).
|
||||
|
||||
## Примеры в репозитории
|
||||
|
||||
| Path | Назначение |
|
||||
|---|---|
|
||||
| `examples/python/openstack_smoke.py` | Multi-port GET smoke |
|
||||
| `examples/python/openstack_conformance.py` | Write-path sample |
|
||||
| `examples/python/openstack_surface_probe.py` | Полный lifecycle probe пакета |
|
||||
|
||||
Cookbook'и: [examples/overview.md](examples/overview.md).
|
||||
@@ -0,0 +1,59 @@
|
||||
**Language / Язык:** [English](../configuration.md) | [Русский](configuration.md)
|
||||
|
||||
# Конфигурация
|
||||
|
||||
## Переменные окружения
|
||||
|
||||
| Переменная | По умолчанию | Назначение |
|
||||
|---|---|---|
|
||||
| `APP_HOST` | `0.0.0.0` | Адрес привязки |
|
||||
| `APP_PORT` | `8080` | Внутренний порт FastAPI (не публичный порт Keystone) |
|
||||
| `DATABASE_URL` | (compose/helm) | PostgreSQL DSN |
|
||||
| `TICKET_SIGNING_KEY` | lab secret | Материал подписи токенов (ротируйте в общих лабораториях) |
|
||||
| `LOG_LEVEL` | `INFO` | Уровень логирования |
|
||||
| `OPENSTACK_SERIES` | `dalmatian` | Серия contract-пакета при холодном старте |
|
||||
| `REQUEST_ID_HEADER` | `X-Request-ID` | Заголовок корреляции запросов |
|
||||
| `SEED_PROFILE` | `minimal` | Для `seed_cli` / Helm seed Job (`minimal` / `demo`) |
|
||||
|
||||
## Compose
|
||||
|
||||
| Файл | Роль |
|
||||
|---|---|
|
||||
| `docker-compose.yml` | Dev-стек (build + bind mounts) |
|
||||
| `docker-compose.release.yml` | Опубликованный Hub-образ |
|
||||
| `.env` / `.env.example` | Локальные переопределения |
|
||||
|
||||
Сервисы:
|
||||
|
||||
- **simulator** — FastAPI на внутреннем `8080`
|
||||
- **api-gateway** — nginx, публикующий реальные порты API OpenStack 1:1 ([ports.md](ports.md))
|
||||
- **postgres** — `postgres:17.5-bookworm` на хосте `127.0.0.1:5433`
|
||||
|
||||
## Helm
|
||||
|
||||
См. [kubernetes.md](kubernetes.md) и
|
||||
[`helm/openstack-api-simulator/values.yaml`](../../helm/openstack-api-simulator/values.yaml).
|
||||
|
||||
Важные параметры:
|
||||
|
||||
| Value | Назначение |
|
||||
|---|---|
|
||||
| `gateway.enabled` | Multi-port nginx (по умолчанию `true`) |
|
||||
| `config.openstackSeries` | Env `OPENSTACK_SERIES` |
|
||||
| `seed.profile` | `minimal` / `demo` |
|
||||
| `postgresql.enabled` | Встроенная БД |
|
||||
| `secret.ticketSigningKey` | Нужно ротировать для общих кластеров |
|
||||
|
||||
## Contract-пакеты
|
||||
|
||||
Расположение: `contracts/openstack/<series>/`.
|
||||
|
||||
В каждой серии — per-service пакеты `api.json`, потребляемые schema-движком.
|
||||
Специализированные роутеры (Keystone, Nova, Neutron, …) остаются stateful для happy-path'ов.
|
||||
|
||||
## Переопределения Web UI
|
||||
|
||||
Environment drawer → **OpenStack API pack**:
|
||||
|
||||
- Активация серии (hot remount)
|
||||
- Переопределение microversion по сервисам
|
||||
@@ -0,0 +1,22 @@
|
||||
**Language / Язык:** [English](../../domains/README.md) | [Русский](README.md)
|
||||
|
||||
# Домены сервисов OpenStack
|
||||
|
||||
Руководства по основным специализированным поверхностям. Pack-only сервисы
|
||||
(Barbican, Manila, Designate, …) покрываются schema-движком и засеваются в
|
||||
`os_api_objects` — см. [api-surface.md](../api-surface.md) и
|
||||
[api_coverage.md](../api_coverage.md).
|
||||
|
||||
| Руководство | Сервис | Порт |
|
||||
|---|---|---|
|
||||
| [keystone.md](keystone.md) | Identity | 5000 |
|
||||
| [nova.md](nova.md) | Compute | 8774 |
|
||||
| [neutron.md](neutron.md) | Network | 9696 |
|
||||
| [glance.md](glance.md) | Image | 9292 |
|
||||
| [cinder.md](cinder.md) | Block storage | 8776 |
|
||||
| [placement.md](placement.md) | Placement | 8003 |
|
||||
| [heat.md](heat.md) | Orchestration | 8004 |
|
||||
| [swift.md](swift.md) | Object storage | 8080 |
|
||||
| [ironic.md](ironic.md) | Bare metal | 6385 |
|
||||
| [octavia.md](octavia.md) | Load balancer | 9876 |
|
||||
| [schema-services.md](schema-services.md) | Остальные pack-сервисы | разные |
|
||||
@@ -0,0 +1,10 @@
|
||||
**Language / Язык:** [English](../../domains/cinder.md) | [Русский](cinder.md)
|
||||
|
||||
# Cinder (block storage)
|
||||
|
||||
Порт **8776**. Пути под `/v3/` (и `/v3/{project_id}/…`).
|
||||
|
||||
## Stateful
|
||||
|
||||
CRUD томов. Demo cloud: ~600 volumes (`in-use` / `available`).
|
||||
Snapshots, types, backups и связанные коллекции — pack/schema-backed.
|
||||
@@ -0,0 +1,10 @@
|
||||
**Language / Язык:** [English](../../domains/glance.md) | [Русский](glance.md)
|
||||
|
||||
# Glance (image)
|
||||
|
||||
Порт **9292**. Пути под `/v2/`.
|
||||
|
||||
## Stateful
|
||||
|
||||
Список/просмотр/создание/обновление/удаление образов; публичные и project-owned
|
||||
images. Members/tags обслуживаются из `os_api_objects` в demo seed.
|
||||
@@ -0,0 +1,11 @@
|
||||
**Language / Язык:** [English](../../domains/heat.md) | [Русский](heat.md)
|
||||
|
||||
# Heat (orchestration)
|
||||
|
||||
Порт **8004**. Пути `/v1/{tenant_id}/…`.
|
||||
|
||||
## Stateful
|
||||
|
||||
Стеки в `os_stacks`. Demo seed добавляет stacks плюс вложенные строки
|
||||
`stack_resource` / `stack_event` / `software_config` / `software_deployment`
|
||||
для pack GET-probe'ов.
|
||||
@@ -0,0 +1,10 @@
|
||||
**Language / Язык:** [English](../../domains/ironic.md) | [Русский](ironic.md)
|
||||
|
||||
# Ironic (bare metal)
|
||||
|
||||
Порт **6385**.
|
||||
|
||||
## Stateful
|
||||
|
||||
Nodes в `os_nodes`. Demo seed создаёт пул ironic-нод; ports/chassis/
|
||||
allocations — schema-backed примеры.
|
||||
@@ -0,0 +1,21 @@
|
||||
**Language / Язык:** [English](../../domains/keystone.md) | [Русский](keystone.md)
|
||||
|
||||
# Keystone (identity)
|
||||
|
||||
Порт **5000**. Пути под `/v3/`.
|
||||
|
||||
## Реализовано (lab)
|
||||
|
||||
- `POST /v3/auth/tokens` — password auth, project scope
|
||||
- Catalog с multi-port endpoints
|
||||
- Projects, users, roles, role assignments (seed + CRUD через pack/schema)
|
||||
- Domains (`Default`)
|
||||
|
||||
## Seed
|
||||
|
||||
Профили minimal и demo создают домен `Default`, роли `admin`/`member` и
|
||||
пользователей, описанных в [authentication.md](../authentication.md).
|
||||
|
||||
## Примечания
|
||||
|
||||
Federation, application credentials и полный policy engine вне scope.
|
||||
@@ -0,0 +1,16 @@
|
||||
**Language / Язык:** [English](../../domains/neutron.md) | [Русский](neutron.md)
|
||||
|
||||
# Neutron (network)
|
||||
|
||||
Порт **9696**. Пути под `/v2.0/`.
|
||||
|
||||
## Stateful-ресурсы
|
||||
|
||||
Networks, subnets, ports, routers, security groups/rules, floating IPs, agents.
|
||||
|
||||
## Schema / seeded-расширения
|
||||
|
||||
QoS, trunks, RBAC, address scopes, subnet pools, conntrack helpers, port
|
||||
forwardings, примеры FWaaS/VPNaaS/BGP VPN в demo seed.
|
||||
|
||||
Demo добавляет несколько nets/SGs/routers на проект для реалистичной плотности списков.
|
||||
@@ -0,0 +1,21 @@
|
||||
**Language / Язык:** [English](../../domains/nova.md) | [Русский](nova.md)
|
||||
|
||||
# Nova (compute)
|
||||
|
||||
Порт **8774**. Пути под `/v2.1/`.
|
||||
|
||||
## Stateful-ресурсы
|
||||
|
||||
Servers, flavors, keypairs, server groups, AZ, hypervisors, aggregates,
|
||||
services, migrations, volume/interface attachments, metadata, tags,
|
||||
instance actions, consoles (лабораторные URL).
|
||||
|
||||
## Demo cloud
|
||||
|
||||
~1000 серверов по проектам, metadata/`_tags`, attachments, связанные с volumes
|
||||
и ports.
|
||||
|
||||
## Microversions
|
||||
|
||||
Отправляйте `OpenStack-API-Version: compute X.Y` или legacy-заголовок Nova.
|
||||
Применяются ограничения пакета.
|
||||
@@ -0,0 +1,10 @@
|
||||
**Language / Язык:** [English](../../domains/octavia.md) | [Русский](octavia.md)
|
||||
|
||||
# Octavia (load balancer)
|
||||
|
||||
Порт **9876**. Пути под `/v2/lbaas/…`.
|
||||
|
||||
## Stateful
|
||||
|
||||
Load balancers в `os_loadbalancers`. Listeners/pools/healthmonitors/providers/
|
||||
flavors обслуживаются из `os_api_objects` (demo seed их заполняет).
|
||||
@@ -0,0 +1,10 @@
|
||||
**Language / Язык:** [English](../../domains/placement.md) | [Русский](placement.md)
|
||||
|
||||
# Placement
|
||||
|
||||
Порт **8003**.
|
||||
|
||||
## Поведение в лаборатории
|
||||
|
||||
- `GET /resource_providers` — из demo `os_api_objects` (или fallback stub)
|
||||
- `GET/PUT /allocations/{consumer_uuid}` — сохраняемые allocations с lab fallback
|
||||
@@ -0,0 +1,14 @@
|
||||
**Language / Язык:** [English](../../domains/schema-services.md) | [Русский](schema-services.md)
|
||||
|
||||
# Schema-backed сервисы
|
||||
|
||||
Эти проекты в основном обслуживаются contract-пакетами + `os_api_objects`
|
||||
(demo seed вставляет несколько строк на тип ресурса):
|
||||
|
||||
Barbican, Manila, Designate, Magnum, Zun, Trove, Mistral, Aodh, CloudKitty,
|
||||
Freezer, Blazar, Vitrage, Masakari, Tacker, Adjutant, Watcher, Zaqar, Heat-CFN.
|
||||
|
||||
Порты: [ports.md](../ports.md). Операции: [api_coverage.md](../api_coverage.md).
|
||||
|
||||
CRUD lifecycle проверяется через `examples/python/openstack_surface_probe.py`
|
||||
и `tests/openstack/conformance/`.
|
||||
@@ -0,0 +1,10 @@
|
||||
**Language / Язык:** [English](../../domains/swift.md) | [Русский](swift.md)
|
||||
|
||||
# Swift (object storage)
|
||||
|
||||
Порт **8080** на **gateway** (внутренний simulator остаётся на 8080 за nginx).
|
||||
|
||||
## Stateful
|
||||
|
||||
Accounts/containers/objects в таблицах `os_swift_*`. Demo seed создаёт
|
||||
контейнеры `images` / `backups` / `artifacts` с readme-объектом на проект.
|
||||
@@ -0,0 +1,19 @@
|
||||
**Language / Язык:** [English](../../examples/ansible.md) | [Русский](ansible.md)
|
||||
|
||||
# Ansible (openstack.cloud)
|
||||
|
||||
## Cookbook (один stack)
|
||||
|
||||
[`examples/ansible/playbook.yml`](../../../examples/ansible/playbook.yml) —
|
||||
`ansible.builtin.uri` против Keystone/Nova/Neutron/Glance.
|
||||
|
||||
```bash
|
||||
make up && make seed-demo
|
||||
cd examples/ansible
|
||||
ansible-playbook -i inventory.ini playbook.yml
|
||||
```
|
||||
|
||||
Auth: `http://127.0.0.1:5000/v3`, `admin` / `secret`, проект `demo`.
|
||||
|
||||
Интеграционное покрытие API теперь в [`pulumi-tests/`](../../../pulumi-tests/)
|
||||
(Pulumi / `pulumi_openstack`). См. [hypervisor-lab.md](../hypervisor-lab.md).
|
||||
@@ -0,0 +1,21 @@
|
||||
**Language / Язык:** [English](../../examples/openstack-cli.md) | [Русский](openstack-cli.md)
|
||||
|
||||
# OpenStack CLI
|
||||
|
||||
Типовой набор переменных окружения и команд против локального gateway:
|
||||
|
||||
```bash
|
||||
export OS_AUTH_URL=http://127.0.0.1:5000/v3
|
||||
export OS_USERNAME=admin
|
||||
export OS_PASSWORD=secret
|
||||
export OS_PROJECT_NAME=demo
|
||||
export OS_USER_DOMAIN_NAME=Default
|
||||
export OS_PROJECT_DOMAIN_NAME=Default
|
||||
export OS_IDENTITY_API_VERSION=3
|
||||
|
||||
openstack token issue
|
||||
openstack server list
|
||||
openstack network list
|
||||
openstack volume list
|
||||
openstack stack list
|
||||
```
|
||||
@@ -0,0 +1,53 @@
|
||||
**Language / Язык:** [English](../../examples/overview.md) | [Русский](overview.md)
|
||||
|
||||
# Обзор примеров клиентов
|
||||
|
||||
Исполняемые скрипты — в [`examples/`](../../../examples/).
|
||||
Лаборатория покрытия API на Pulumi — в [`pulumi-tests/`](../../../pulumi-tests/).
|
||||
|
||||
## Краткая справка
|
||||
|
||||
| Path | Tool | Purpose |
|
||||
|---|---|---|
|
||||
| `examples/python/openstacksdk_cookbook.py` | openstacksdk | net + server + volume lifecycle |
|
||||
| `examples/ansible/playbook.yml` | Ansible `uri` | минимальный Keystone/Nova/Neutron |
|
||||
| `examples/terraform/main.tf` | Terraform | `openstack_compute_instance_v2` + volume |
|
||||
| `examples/pulumi/` | Pulumi | `pulumi_openstack` Instance + Network |
|
||||
| `examples/run_iac_stack.sh` | все четыре | последовательный smoke cookbook'ов |
|
||||
| `pulumi-tests/` | Pulumi | каждая pack-операция × yoga→dalmatian + HTML-отчёт |
|
||||
|
||||
## Auth
|
||||
|
||||
1. `POST /v3/auth/tokens` → `X-Subject-Token`
|
||||
2. Вызовы сервисов с `X-Auth-Token` на нужном [порту](../ports.md)
|
||||
|
||||
Лаборатория по умолчанию: `admin` / `secret`, проект `demo`, домен `Default`.
|
||||
|
||||
## Cookbook'и
|
||||
|
||||
- [Python (requests)](python-requests.md)
|
||||
- [Python (openstacksdk)](python-openstacksdk.md)
|
||||
- [Ansible](ansible.md)
|
||||
- [Terraform](terraform.md)
|
||||
- [Pulumi](pulumi.md)
|
||||
- [CLI](openstack-cli.md)
|
||||
- [Troubleshooting](troubleshooting-clients.md)
|
||||
|
||||
## Лаборатория покрытия API (Pulumi)
|
||||
|
||||
Полное руководство: [hypervisor-lab.md](../hypervisor-lab.md)
|
||||
|
||||
```bash
|
||||
cd pulumi-tests
|
||||
make up
|
||||
make test-pulumi-smoke
|
||||
make test-pulumi
|
||||
open reports/pulumi-report.html
|
||||
```
|
||||
|
||||
Probe-скрипты:
|
||||
|
||||
| Script | Purpose |
|
||||
|---|---|
|
||||
| `examples/python/openstack_smoke.py` | Multi-port GET smoke |
|
||||
| `examples/python/openstack_surface_probe.py` | Pack operation probe (также используется Pulumi-лабой) |
|
||||
@@ -0,0 +1,30 @@
|
||||
**Language / Язык:** [English](../../examples/pulumi.md) | [Русский](pulumi.md)
|
||||
|
||||
# Pulumi (pulumi_openstack)
|
||||
|
||||
## Cookbook (один stack)
|
||||
|
||||
[`examples/pulumi/`](../../../examples/pulumi/) — `pulumi_openstack` Instance,
|
||||
Network, Subnet.
|
||||
|
||||
```bash
|
||||
make up && make seed-demo
|
||||
cd examples/pulumi
|
||||
pulumi stack init dev --secrets-provider passphrase
|
||||
export PULUMI_CONFIG_PASSPHRASE=lab
|
||||
pulumi up
|
||||
pulumi destroy
|
||||
```
|
||||
|
||||
## Лаборатория покрытия (`pulumi-tests`)
|
||||
|
||||
[`pulumi-tests/`](../../../pulumi-tests/) — стеки `pulumi_openstack` на каждую
|
||||
серию, проверка непустых export'ов, затем HTTP-probe pack-операций с
|
||||
непустыми телами.
|
||||
|
||||
```bash
|
||||
make pulumi-tests
|
||||
open pulumi-tests/reports/pulumi-report.html
|
||||
```
|
||||
|
||||
См. [hypervisor-lab.md](../hypervisor-lab.md).
|
||||
@@ -0,0 +1,24 @@
|
||||
**Language / Язык:** [English](../../examples/python-openstacksdk.md) | [Русский](python-openstacksdk.md)
|
||||
|
||||
# Python + openstacksdk
|
||||
|
||||
```python
|
||||
import openstack
|
||||
|
||||
conn = openstack.connect(
|
||||
auth_url="http://127.0.0.1:5000/v3",
|
||||
project_name="demo",
|
||||
username="admin",
|
||||
password="secret",
|
||||
user_domain_name="Default",
|
||||
project_domain_name="Default",
|
||||
)
|
||||
|
||||
for server in conn.compute.servers():
|
||||
print(server.name, server.status)
|
||||
for network in conn.network.networks():
|
||||
print(network.name)
|
||||
```
|
||||
|
||||
Убедитесь, что порты из service catalog доступны (Compose gateway или Helm
|
||||
port-forward). См. [clients.md](../clients.md).
|
||||
@@ -0,0 +1,37 @@
|
||||
**Language / Язык:** [English](../../examples/python-requests.md) | [Русский](python-requests.md)
|
||||
|
||||
# Python + requests
|
||||
|
||||
Минимальный пример password-auth и списка серверов Nova:
|
||||
|
||||
```python
|
||||
import requests
|
||||
|
||||
AUTH = "http://127.0.0.1:5000/v3/auth/tokens"
|
||||
r = requests.post(
|
||||
AUTH,
|
||||
json={
|
||||
"auth": {
|
||||
"identity": {
|
||||
"methods": ["password"],
|
||||
"password": {
|
||||
"user": {
|
||||
"name": "admin",
|
||||
"domain": {"name": "Default"},
|
||||
"password": "secret",
|
||||
}
|
||||
},
|
||||
},
|
||||
"scope": {
|
||||
"project": {"name": "demo", "domain": {"name": "Default"}}
|
||||
},
|
||||
}
|
||||
},
|
||||
)
|
||||
r.raise_for_status()
|
||||
token = r.headers["X-Subject-Token"]
|
||||
headers = {"X-Auth-Token": token}
|
||||
|
||||
servers = requests.get("http://127.0.0.1:8774/v2.1/servers", headers=headers)
|
||||
print(servers.status_code, len(servers.json().get("servers", [])))
|
||||
```
|
||||
@@ -0,0 +1,21 @@
|
||||
**Language / Язык:** [English](../../examples/terraform.md) | [Русский](terraform.md)
|
||||
|
||||
# Terraform (openstack provider)
|
||||
|
||||
## Cookbook (один stack)
|
||||
|
||||
[`examples/terraform/main.tf`](../../../examples/terraform/main.tf) —
|
||||
**`terraform-provider-openstack/openstack`**.
|
||||
|
||||
```bash
|
||||
make up && make seed-demo
|
||||
cd examples/terraform
|
||||
terraform init
|
||||
terraform apply
|
||||
terraform destroy
|
||||
```
|
||||
|
||||
По умолчанию: `auth_url = http://127.0.0.1:5000/v3`, `admin` / `secret`, проект `demo`.
|
||||
|
||||
Интеграционное покрытие API — в [`pulumi-tests/`](../../../pulumi-tests/)
|
||||
(Pulumi / `pulumi_openstack`). См. [hypervisor-lab.md](../hypervisor-lab.md).
|
||||
@@ -0,0 +1,27 @@
|
||||
**Language / Язык:** [English](../../examples/troubleshooting-clients.md) | [Русский](troubleshooting-clients.md)
|
||||
|
||||
# Устранение неполадок клиентов
|
||||
|
||||
## Каталог указывает на недоступные хосты
|
||||
|
||||
Seed-каталог в некоторых конфигурациях использует `host.docker.internal` или
|
||||
имена compose-сервисов. Переопределите endpoints или используйте host gateway,
|
||||
который вы реально публикуете (`127.0.0.1` с port-forward).
|
||||
|
||||
## SSL-ошибки против Ingress
|
||||
|
||||
Staging-issuers лаборатории не доверенные — используйте `curl -k` /
|
||||
`OS_INSECURE=true` только в lab.
|
||||
|
||||
## Пустой список серверов
|
||||
|
||||
Неверный project scope или demo не загружен. Проверьте:
|
||||
|
||||
```bash
|
||||
openstack project list
|
||||
make seed-demo
|
||||
```
|
||||
|
||||
## Microversion отклонён
|
||||
|
||||
Понизьте запрошенную compute microversion или сбросьте переопределения в Web UI.
|
||||
@@ -0,0 +1,39 @@
|
||||
**Language / Язык:** [English](../faq.md) | [Русский](faq.md)
|
||||
|
||||
# FAQ
|
||||
|
||||
## Это настоящее OpenStack cloud?
|
||||
|
||||
Нет. Это **surface-complete API laboratory**: состояние в PostgreSQL,
|
||||
ответы в форме API-ref, без оркестрации гипервизора.
|
||||
|
||||
## Какой релиз использовать?
|
||||
|
||||
По умолчанию пакет **Dalmatian**. Переключайте через `OPENSTACK_SERIES` или Web UI.
|
||||
См. [api-versions.md](api-versions.md).
|
||||
|
||||
## Compose vs Helm?
|
||||
|
||||
| Need | Use |
|
||||
|---|---|
|
||||
| Local hack / CI on Docker | Compose |
|
||||
| Cluster + Ingress TLS | Helm ([kubernetes.md](kubernetes.md)) |
|
||||
|
||||
## Зачем так много портов?
|
||||
|
||||
Service catalog OpenStack ожидает отдельные endpoints. api-gateway публикует
|
||||
[реальную матрицу портов по умолчанию](ports.md) **один в один** (без смещения на хосте).
|
||||
|
||||
## Demo cloud стёр мои ресурсы
|
||||
|
||||
Lifecycle-тесты и reseed очищают lab tables. Перезагрузите через `make seed-demo`.
|
||||
|
||||
## Можно ли направить Terraform / Ansible сюда?
|
||||
|
||||
Да — используйте Keystone URL и seed credentials. Ожидайте lab limitations
|
||||
(policy, async workflows, Ceph и т.д.). См. [clients.md](clients.md).
|
||||
|
||||
## Где Helm chart?
|
||||
|
||||
[`helm/openstack-api-simulator`](../../helm/openstack-api-simulator/README.ru.md) — руководство в
|
||||
[kubernetes.md](kubernetes.md).
|
||||
@@ -0,0 +1,123 @@
|
||||
**Language / Язык:** [English](../getting-started.md) | [Русский](getting-started.md)
|
||||
|
||||
# Быстрый старт
|
||||
|
||||
Сквозная первая лабораторная сессия на Docker Compose. Для Kubernetes см.
|
||||
[kubernetes.md](kubernetes.md).
|
||||
|
||||
## Требования
|
||||
|
||||
- Docker / Docker Compose
|
||||
- Python 3.13+ (опционально, для smoke-скриптов на хосте)
|
||||
- `curl` или OpenStack CLI / `openstacksdk`
|
||||
|
||||
## Выберите путь
|
||||
|
||||
| Путь | Когда |
|
||||
|---|---|
|
||||
| **1a. Опубликованный образ** | Лаборатория с Hub-образом (`docker-compose.release.yml`; нужен checkout репо для mount gateway/TLS) |
|
||||
| **1b. Development checkout** | Будете менять код / пакеты |
|
||||
| **Helm** | Установка в кластер — [kubernetes.md](kubernetes.md) |
|
||||
|
||||
## 1a. Опубликованный образ (Docker Hub)
|
||||
|
||||
Нужен **git checkout** этого репозитория: Compose монтирует
|
||||
`./docker/gateway` и `./docker/tls` в nginx gateway. Контейнер симулятора
|
||||
берётся с Docker Hub (локальная сборка приложения не нужна).
|
||||
|
||||
```bash
|
||||
git clone https://github.com/inecs/openstack-api-simulator.git
|
||||
cd openstack-api-simulator
|
||||
docker compose -f docker-compose.release.yml up -d --wait
|
||||
# или: make release-up
|
||||
```
|
||||
|
||||
Образ: [`inecs/openstack-api-simulator`](https://hub.docker.com/r/inecs/openstack-api-simulator).
|
||||
Тег при необходимости: `IMAGE_TAG=0.1.0`.
|
||||
|
||||
## 1b. Development checkout
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
docker compose up -d --build --wait
|
||||
```
|
||||
|
||||
## 2. Дождитесь готовности
|
||||
|
||||
```bash
|
||||
curl -sf http://127.0.0.1:5000/health/ready
|
||||
```
|
||||
|
||||
## 3. Загрузите seed-профиль
|
||||
|
||||
Minimal seed выполняется при первом старте. Опционально — полное синтетическое облако:
|
||||
|
||||
```bash
|
||||
make seed-demo
|
||||
# или
|
||||
docker compose exec simulator python -m app.openstack.seed_cli --profile demo
|
||||
```
|
||||
|
||||
Профили: [seed-profiles.md](seed-profiles.md).
|
||||
|
||||
## 4. Аутентификация (Keystone)
|
||||
|
||||
```bash
|
||||
export OS_AUTH_URL=http://127.0.0.1:5000/v3
|
||||
TOKEN=$(curl -si -X POST "$OS_AUTH_URL/auth/tokens" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{
|
||||
"auth": {
|
||||
"identity": {
|
||||
"methods": ["password"],
|
||||
"password": {
|
||||
"user": {
|
||||
"name": "admin",
|
||||
"domain": {"name": "Default"},
|
||||
"password": "secret"
|
||||
}
|
||||
}
|
||||
},
|
||||
"scope": {
|
||||
"project": {"name": "demo", "domain": {"name": "Default"}}
|
||||
}
|
||||
}
|
||||
}' | awk -F': ' 'tolower($1)=="x-subject-token"{print $2}' | tr -d '\r')
|
||||
echo "token=$TOKEN"
|
||||
```
|
||||
|
||||
## 5. Вызовы Nova / Neutron
|
||||
|
||||
```bash
|
||||
curl -sH "X-Auth-Token: $TOKEN" http://127.0.0.1:8774/v2.1/servers/detail | head -c 400
|
||||
curl -sH "X-Auth-Token: $TOKEN" http://127.0.0.1:9696/v2.0/networks
|
||||
```
|
||||
|
||||
## 6. Откройте Web UI
|
||||
|
||||
[http://localhost:5000/](http://localhost:5000/) — консоль, Environment drawer
|
||||
(серия OpenStack pack + microversions), Data drawer (загрузка/выгрузка demo cloud).
|
||||
|
||||
## 7. Smoke / conformance
|
||||
|
||||
```bash
|
||||
make smoke
|
||||
python3 examples/python/openstack_smoke.py
|
||||
python3 examples/python/openstack_conformance.py
|
||||
```
|
||||
|
||||
## Готово, когда…
|
||||
|
||||
- `/health/ready` возвращает 200
|
||||
- Keystone выдаёт `X-Subject-Token`
|
||||
- списки Nova/Neutron содержат seed-ресурсы
|
||||
- (опционально) demo cloud показывает ~1000 серверов
|
||||
|
||||
## Дальше
|
||||
|
||||
- [Порты](ports.md) — полная матрица портов сервисов
|
||||
- [Покрытие API](api_coverage.md) — операции пакетов по сериям
|
||||
- [Клиенты](clients.md) — openstacksdk / CLI
|
||||
- [Kubernetes / Helm](kubernetes.md)
|
||||
- [Hypervisor-lab](hypervisor-lab.md) — Pulumi-покрытие API (все ops × серии)
|
||||
- [Эксплуатация](operations.md)
|
||||
@@ -0,0 +1,33 @@
|
||||
**Language / Язык:** [English](../hypervisor-lab.md) | [Русский](hypervisor-lab.md)
|
||||
|
||||
# Лаборатория покрытия Pulumi OpenStack
|
||||
|
||||
Сьют в [`pulumi-tests/`](../../pulumi-tests/): максимально **`pulumi_openstack`**,
|
||||
затем HTTP-probe pack-операций с проверкой **непустых** ответов для серий
|
||||
**yoga → dalmatian**.
|
||||
|
||||
## Быстрый старт
|
||||
|
||||
```bash
|
||||
make pulumi-tests # из корня (полный сьют)
|
||||
make test-pulumi-smoke # быстрый режим
|
||||
```
|
||||
|
||||
Или:
|
||||
|
||||
```bash
|
||||
cd pulumi-tests
|
||||
make up && make build
|
||||
make test-pulumi
|
||||
open reports/pulumi-report.html
|
||||
```
|
||||
|
||||
## Ход (на серию)
|
||||
|
||||
1. Активация pack серии
|
||||
2. Pulumi Automation API → `programs/os_coverage` (`pulumi_openstack`)
|
||||
3. Каждый export стека должен быть непустым
|
||||
4. HTTP-probe pack-операций; непустые тела на успешных GET/POST
|
||||
5. Destroy; HTML + JUnit
|
||||
|
||||
См. [`pulumi-tests/README.ru.md`](../../pulumi-tests/README.ru.md).
|
||||
@@ -0,0 +1,184 @@
|
||||
**Language / Язык:** [English](../kubernetes.md) | [Русский](kubernetes.md)
|
||||
|
||||
# Kubernetes / Helm
|
||||
|
||||
Развёртывание опубликованного runtime-образа с Docker Hub чартом
|
||||
[`helm/openstack-api-simulator`](../../helm/openstack-api-simulator/README.ru.md).
|
||||
|
||||
Образ: [`inecs/openstack-api-simulator`](https://hub.docker.com/r/inecs/openstack-api-simulator)
|
||||
|
||||
Чарт зеркалирует Docker Compose:
|
||||
|
||||
| Компонент | Роль |
|
||||
|---|---|
|
||||
| **simulator** Deployment | FastAPI-приложение на `:8080` |
|
||||
| **api-gateway** Deployment | nginx multi-port шлюз OpenStack |
|
||||
| **PostgreSQL** StatefulSet | Встроенный Postgres 17 (опционально) |
|
||||
| **migrate** initContainer | Идемпотентные миграции схемы |
|
||||
| **seed** Job (опционально) | Лабораторные данные `minimal` или `demo` |
|
||||
|
||||
## Требования
|
||||
|
||||
- Kubernetes 1.27+ (или аналог)
|
||||
- Helm 3.14+
|
||||
- Для Ingress TLS: [Ingress NGINX](https://kubernetes.github.io/ingress-nginx/) и
|
||||
[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 release + Ingress + Let's Encrypt)
|
||||
|
||||
Из git checkout этого репозитория:
|
||||
|
||||
```bash
|
||||
helm upgrade --install os-sim ./helm/openstack-api-simulator \
|
||||
-n openstack-sim --create-namespace \
|
||||
-f ./helm/openstack-api-simulator/values-ingress-example.yaml \
|
||||
--set certManager.email=you@example.com \
|
||||
--set ingress.hosts[0].host=os-sim.example.com \
|
||||
--set ingress.tls[0].hosts[0]=os-sim.example.com \
|
||||
--set secret.ticketSigningKey="$(openssl rand -hex 32)" \
|
||||
--set postgresql.auth.password="$(openssl rand -hex 16)"
|
||||
```
|
||||
|
||||
Что происходит:
|
||||
|
||||
1. Скачивается `inecs/openstack-api-simulator:0.1.0`.
|
||||
2. Устанавливается PostgreSQL 17 (`postgres:17.5-bookworm`).
|
||||
3. Выполняются миграции схемы в init-контейнере (идемпотентно).
|
||||
4. Засевается профиль **demo** (`seed.enabled=true`, ~1000 серверов).
|
||||
5. Разворачивается nginx **api-gateway** со стандартными портами OpenStack (5000, 8774, 9696, …).
|
||||
6. Создаются ресурсы `ClusterIssuer` (`letsencrypt-prod` / `letsencrypt-staging`).
|
||||
7. Создаётся Ingress → gateway `:5000` (Keystone + Web UI) с TLS.
|
||||
|
||||
DNS для `os-sim.example.com` должен указывать на Ingress controller. Затем:
|
||||
|
||||
```bash
|
||||
kubectl -n openstack-sim get certificate,ingress,pods
|
||||
curl -sS https://os-sim.example.com/health/ready
|
||||
open https://os-sim.example.com/
|
||||
```
|
||||
|
||||
Логин по умолчанию: `admin` / `secret` (проект `demo` или `admin`, домен `Default`).
|
||||
|
||||
### Сначала staging (рекомендуется)
|
||||
|
||||
```bash
|
||||
helm upgrade --install os-sim ./helm/openstack-api-simulator \
|
||||
-n openstack-sim --create-namespace \
|
||||
-f ./helm/openstack-api-simulator/values-ingress-example.yaml \
|
||||
--set certManager.email=you@example.com \
|
||||
--set certManager.useStaging=true \
|
||||
--set ingress.hosts[0].host=os-sim.example.com \
|
||||
--set ingress.tls[0].hosts[0]=os-sim.example.com \
|
||||
--set secret.ticketSigningKey="$(openssl rand -hex 32)"
|
||||
```
|
||||
|
||||
Используйте `curl -k` против staging CA. Для production переключите `certManager.useStaging=false`.
|
||||
|
||||
## Минимальная установка (ClusterIP + port-forward)
|
||||
|
||||
```bash
|
||||
helm upgrade --install os-sim ./helm/openstack-api-simulator \
|
||||
-n openstack-sim --create-namespace \
|
||||
--set secret.ticketSigningKey="$(openssl rand -hex 32)" \
|
||||
--set seed.enabled=true \
|
||||
--set seed.profile=minimal
|
||||
|
||||
kubectl -n openstack-sim port-forward \
|
||||
svc/os-sim-openstack-api-simulator-gateway \
|
||||
5000:5000 8774:8774 9696:9696 9292:9292 8776:8776
|
||||
```
|
||||
|
||||
| URL | Сервис |
|
||||
|---|---|
|
||||
| http://127.0.0.1:5000/ | Keystone + консоль |
|
||||
| http://127.0.0.1:8774/v2.1/ | Nova |
|
||||
| http://127.0.0.1:9696/v2.0/ | Neutron |
|
||||
|
||||
Полная матрица портов: [ports.md](ports.md).
|
||||
|
||||
## Внешний PostgreSQL
|
||||
|
||||
```bash
|
||||
helm upgrade --install os-sim ./helm/openstack-api-simulator \
|
||||
-n openstack-sim --create-namespace \
|
||||
--set postgresql.enabled=false \
|
||||
--set secret.ticketSigningKey="$(openssl rand -hex 32)" \
|
||||
--set secret.databaseUrl='postgresql://user:pass@pg.example.com:5432/openstack_simulator'
|
||||
```
|
||||
|
||||
Или `secret.existingSecret` с ключами `DATABASE_URL` и `TICKET_SIGNING_KEY`.
|
||||
|
||||
## Как работает api-gateway
|
||||
|
||||
Та же модель, что и в Compose (`docker/gateway/openstack-ports.conf`):
|
||||
|
||||
1. Клиент подключается к **порту сервиса** (например Nova `8774`).
|
||||
2. nginx выставляет `X-OpenStack-Service` и `X-Forwarded-Port`.
|
||||
3. FastAPI переписывает путь в `/_os/<service>/…`, чтобы `/v3` (Keystone vs Cinder) не конфликтовал.
|
||||
|
||||
Ingress (если включён) обслуживает **Keystone/UI на порту 5000**. Для Nova/Neutron
|
||||
извне кластера:
|
||||
|
||||
- `kubectl port-forward` дополнительных портов, или
|
||||
- expose `*-gateway` как `LoadBalancer` / `NodePort` (`gateway.service.type`), или
|
||||
- дополнительные Ingress rules / TCP-сервисы для этих портов.
|
||||
|
||||
## Как выпускается TLS
|
||||
|
||||
При `certManager.enabled=true` и `certManager.createClusterIssuer=true` чарт
|
||||
создаёт ACME `ClusterIssuer` (HTTP-01). Шаблон Ingress добавляет:
|
||||
|
||||
```yaml
|
||||
metadata:
|
||||
annotations:
|
||||
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||
spec:
|
||||
tls:
|
||||
- secretName: openstack-api-simulator-tls
|
||||
hosts: [os-sim.example.com]
|
||||
```
|
||||
|
||||
Чарт **не** устанавливает cert-manager или Ingress controller.
|
||||
|
||||
## Эксплуатация
|
||||
|
||||
```bash
|
||||
# логи
|
||||
kubectl -n openstack-sim logs -l app.kubernetes.io/component=simulator -f
|
||||
kubectl -n openstack-sim logs -l app.kubernetes.io/component=gateway -f
|
||||
|
||||
# reseed minimal
|
||||
kubectl -n openstack-sim exec deploy/os-sim-openstack-api-simulator -- \
|
||||
python -m app.openstack.seed_cli --profile minimal
|
||||
|
||||
# reseed demo cloud
|
||||
kubectl -n openstack-sim exec deploy/os-sim-openstack-api-simulator -- \
|
||||
python -m app.openstack.seed_cli --profile demo
|
||||
|
||||
# активировать серию OpenStack pack
|
||||
kubectl -n openstack-sim set env deploy/os-sim-openstack-api-simulator \
|
||||
OPENSTACK_SERIES=caracal
|
||||
# затем перезапустить pod / helm upgrade с --set config.openstackSeries=caracal
|
||||
|
||||
# удаление
|
||||
helm -n openstack-sim uninstall os-sim
|
||||
```
|
||||
|
||||
## Справка по values
|
||||
|
||||
См. [`helm/openstack-api-simulator/values.yaml`](../../helm/openstack-api-simulator/values.yaml)
|
||||
и [README чарта](../../helm/openstack-api-simulator/README.ru.md).
|
||||
|
||||
Связанные документы:
|
||||
|
||||
- [Быстрый старт](getting-started.md) — путь Compose
|
||||
- [Эксплуатация](operations.md) — публикация на Docker Hub / day-2
|
||||
- [Порты](ports.md) — матрица портов OpenStack
|
||||
- [Seed-профили](seed-profiles.md) — `minimal` / `demo`
|
||||
- [Безопасность](security.md) — лабораторные учётные данные
|
||||
@@ -0,0 +1,39 @@
|
||||
**Language / Язык:** [English](../observability.md) | [Русский](observability.md)
|
||||
|
||||
# Наблюдаемость
|
||||
|
||||
## Health endpoints
|
||||
|
||||
| Path | Значение |
|
||||
|---|---|
|
||||
| `/health/live` | Процесс работает |
|
||||
| `/health/ready` | БД доступна + миграции применены |
|
||||
|
||||
Оба доступны на simulator и через gateway (на любом опубликованном порту).
|
||||
|
||||
## Request IDs
|
||||
|
||||
Заголовок `X-Request-ID` (настраивается через `REQUEST_ID_HEADER`) принимается и
|
||||
эхом возвращается там, где применяется middleware.
|
||||
|
||||
## Логи
|
||||
|
||||
Compose:
|
||||
|
||||
```bash
|
||||
make logs
|
||||
docker compose logs -f simulator api-gateway
|
||||
```
|
||||
|
||||
Helm:
|
||||
|
||||
```bash
|
||||
kubectl logs -l app.kubernetes.io/component=simulator -f
|
||||
kubectl logs -l app.kubernetes.io/component=gateway -f
|
||||
```
|
||||
|
||||
## Доказательства совместимости / покрытия
|
||||
|
||||
- Покрытие пакетов: [api_coverage.md](api_coverage.md)
|
||||
- Live lifecycle: `examples/python/openstack_surface_probe.py`
|
||||
- pytest: `tests/openstack/` (включая real-DB conformance)
|
||||
@@ -0,0 +1,117 @@
|
||||
**Language / Язык:** [English](../operations.md) | [Русский](operations.md)
|
||||
|
||||
# Эксплуатация
|
||||
|
||||
## Day-2 команды (Compose)
|
||||
|
||||
```bash
|
||||
make up # start stack
|
||||
make down # stop stack
|
||||
make restart
|
||||
make logs
|
||||
make db-migrate # idempotent migrations
|
||||
make seed # minimal OpenStack seed
|
||||
make seed-demo # demo cloud (~1000 servers)
|
||||
make smoke # multi-service GET smoke
|
||||
```
|
||||
|
||||
## Миграции
|
||||
|
||||
Упорядоченный SQL в `app/db/migrations/` применяется транзакционно.
|
||||
Повторный запуск `make db-migrate` безопасен. `/health/ready` остаётся недоступным,
|
||||
пока миграции не применены. Helm выполняет тот же migrate-шаг как initContainer.
|
||||
|
||||
## Reseed
|
||||
|
||||
```bash
|
||||
make seed # minimal
|
||||
make seed-demo # replaces state with demo cloud
|
||||
```
|
||||
|
||||
Или:
|
||||
|
||||
```bash
|
||||
docker compose exec simulator python -m app.openstack.seed_cli --profile demo
|
||||
```
|
||||
|
||||
Reseed **очищает** лабораторные таблицы OpenStack и перезагружает данные. Внешняя
|
||||
автоматизация с закэшированными UUID ресурсов должна обновить их.
|
||||
|
||||
## OpenStack pack series
|
||||
|
||||
Cold start (env):
|
||||
|
||||
```bash
|
||||
OPENSTACK_SERIES=caracal docker compose up -d
|
||||
```
|
||||
|
||||
Helm:
|
||||
|
||||
```bash
|
||||
--set config.openstackSeries=yoga
|
||||
```
|
||||
|
||||
Hot-swap (Web UI или API):
|
||||
|
||||
```bash
|
||||
curl -X POST http://127.0.0.1:5000/ui/api/openstack/contracts/activate \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"series":"dalmatian"}'
|
||||
```
|
||||
|
||||
Серии: `yoga`, `antelope`, `caracal`, `dalmatian`. Покрытие:
|
||||
[api_coverage.md](api_coverage.md).
|
||||
|
||||
## Перегенерация contract-пакетов
|
||||
|
||||
```bash
|
||||
PYTHONPATH=tools python3 tools/os_api_inventory/generate_packs.py
|
||||
PYTHONPATH=tools python3 tools/os_api_inventory/coverage_report.py
|
||||
```
|
||||
|
||||
## Резервное копирование состояния лаборатории
|
||||
|
||||
PostgreSQL — источник истины. Используйте `pg_dump` / снимки volume.
|
||||
Контейнеры приложения одноразовые, если volume БД сохранён.
|
||||
|
||||
## Публикация на Docker Hub
|
||||
|
||||
```bash
|
||||
docker login
|
||||
make release
|
||||
```
|
||||
|
||||
| Variable | Default | Meaning |
|
||||
|---|---|---|
|
||||
| `DOCKERHUB_USER` | `inecs` | Docker Hub namespace |
|
||||
| `IMAGE_NAME` | `openstack-api-simulator` | Repository name |
|
||||
| `VERSION` | from `pyproject.toml` | Image tag |
|
||||
|
||||
```bash
|
||||
make release VERSION=0.2.0
|
||||
make release-build # local tags only
|
||||
```
|
||||
|
||||
## Kubernetes day-2
|
||||
|
||||
См. [kubernetes.md](kubernetes.md) для логов, reseed через `kubectl exec` и
|
||||
удаления.
|
||||
|
||||
## CI лаборатории покрытия API (pulumi-tests)
|
||||
|
||||
Pulumi прогоняет каждую pack-операцию по сериям — см.
|
||||
[hypervisor-lab.md](hypervisor-lab.md).
|
||||
|
||||
```bash
|
||||
make test-pulumi-smoke # from repo root
|
||||
make test-pulumi
|
||||
```
|
||||
|
||||
Отчёты: `pulumi-tests/reports/pulumi-report.html` и `pulumi-junit.xml`.
|
||||
|
||||
## Обновления
|
||||
|
||||
1. Pull / build нового тега образа.
|
||||
2. Примените миграции (автоматически при старте / Helm initContainer).
|
||||
3. Опционально reseed, если изменилась seed-схема.
|
||||
4. Повторите `make smoke` или lifecycle probes.
|
||||
@@ -0,0 +1,56 @@
|
||||
**Language / Язык:** [English](../ports.md) | [Русский](ports.md)
|
||||
|
||||
# Стандартные порты OpenStack в этом симуляторе
|
||||
|
||||
Справка: [Firewalls and default ports](https://docs.openstack.org/install-guide/firewalls-default-ports.html).
|
||||
|
||||
Это **реальные публичные порты API OpenStack по умолчанию**. Compose и Helm
|
||||
публикуют их **один в один** на хосте / Service (без смещения): хост `5000` —
|
||||
Keystone, хост `8774` — Nova и т.д. Запускайте стек на отдельном хосте/ВМ,
|
||||
чтобы эти порты не пересекались с другими лабораторными симуляторами.
|
||||
|
||||
Клиенты обращаются к **api-gateway** (nginx) — сервис Compose или Helm
|
||||
Deployment/Service `*-gateway`. На каждом listen-порту выставляются
|
||||
`X-OpenStack-Service` и `X-Forwarded-Port`; процесс FastAPI переписывает путь в
|
||||
`/_os/<service>/…`, чтобы пересекающиеся корни API (`/v3`, `/v1`, …) не конфликтовали.
|
||||
|
||||
Типичный auth URL: `http://127.0.0.1:5000/v3` (или HTTPS на `:5000` / `:443`
|
||||
через gateway).
|
||||
|
||||
Список в Helm values: `gateway.service.ports` в
|
||||
[`helm/openstack-api-simulator/values.yaml`](../../helm/openstack-api-simulator/values.yaml).
|
||||
|
||||
| Порт | Сервис | За что отвечает | Основные пути |
|
||||
|------|--------|-----------------|---------------|
|
||||
| 5000 | keystone | Identity — токены, проекты, пользователи, роли, service catalog | `/v3/auth/tokens`, `/v3/projects`, … |
|
||||
| 8774 | nova | Compute — серверы (ВМ), flavors, keypairs, AZ, hypervisors | `/v2.1/servers`, flavors, keypairs, AZ, hypervisors, … |
|
||||
| 9696 | neutron | Network — сети, подсети, порты, роутеры, SG, floating IP | `/v2.0/networks`, subnets, ports, routers, SG, FIPs, QoS, trunks, … |
|
||||
| 9292 | glance | Image — образы | `/v2/images` |
|
||||
| 8776 | cinder | Block storage — тома, снапшоты, типы томов | `/v3/volumes` |
|
||||
| 8003 | placement | Placement — resource providers и inventories | `/resource_providers` |
|
||||
| 8004 | heat | Orchestration — стеки Heat | `/v1/{project_id}/stacks` |
|
||||
| 8000 | heat-cfn | CloudFormation-совместимый API Heat | `/stacks` |
|
||||
| 8080 | swift | Object storage — аккаунты, контейнеры, объекты | `/v1/{account}/{container}/…`, `/info` |
|
||||
| 6385 | ironic | Bare metal — ноды, порты, chassis | `/v1/nodes` |
|
||||
| 9876 | octavia | Load balancing — балансировщики, listeners, pools | `/v2/lbaas/loadbalancers` |
|
||||
| 9311 | barbican | Key manager — секреты, контейнеры | `/v1/secrets` |
|
||||
| 8786 | manila | Shared file systems — shares | `/v2/shares` |
|
||||
| 9001 | designate | DNS — зоны и recordsets | `/v2/zones` |
|
||||
| 9511 | magnum | Container infra — кластеры (например Kubernetes) | `/v1/clusters` |
|
||||
| 9517 | zun | Containers — жизненный цикл контейнеров | `/v1/containers` |
|
||||
| 8779 | trove | Database as a service — экземпляры БД | `/v1.0/instances` |
|
||||
| 8989 | mistral | Workflows | `/v2/workflows` |
|
||||
| 8042 | aodh | Alarming — алармы | `/v2/alarms` |
|
||||
| 8889 | cloudkitty | Rating / биллинг-метрики | `/v1/rating/…` |
|
||||
| 9090 | freezer | Backup — задания резервного копирования | `/v2/jobs` |
|
||||
| 1234 | blazar | Reservation — leases | `/leases` |
|
||||
| 8999 | vitrage | Root cause analysis (RCA) | `/v1/alarm` |
|
||||
| 15868 | masakari | Instance HA — высокая доступность инстансов | `/v1/segments` |
|
||||
| 9890 | tacker | NFV orchestration | `/v1.0/vnfs` |
|
||||
| 5050 | adjutant | Admin workflows / self-service задачи | `/v1/tasks` |
|
||||
| 9322 | watcher | Infrastructure optimization | `/v1/…` |
|
||||
| 8888 | zaqar | Messaging | `/v2/…` |
|
||||
| 80 | http | Reverse proxy консоли (Compose + Helm gateway) | — |
|
||||
| 443 | https | TLS reverse proxy (**только Compose**; в Helm TLS завершается на Ingress) | — |
|
||||
|
||||
Внутренний FastAPI слушает `8080` только внутри Docker (не Swift public port с хоста — хост `8080` это Swift через gateway). Postgres публикуется только как `127.0.0.1:5433` (это не порт OpenStack API).
|
||||
@@ -0,0 +1,33 @@
|
||||
**Language / Язык:** [English](../security.md) | [Русский](security.md)
|
||||
|
||||
# Безопасность
|
||||
|
||||
Этот проект — **лабораторный симулятор**, а не production OpenStack cloud.
|
||||
|
||||
## Граница доверия
|
||||
|
||||
- Пароли по умолчанию (`secret`) намеренно простые для лабораторий.
|
||||
- `TICKET_SIGNING_KEY` / `secret.ticketSigningKey` нужно ротировать перед любым
|
||||
общим или internet-facing развёртыванием.
|
||||
- Пароли bundled Postgres в values/compose — лабораторные defaults.
|
||||
|
||||
## Сетевая экспозиция
|
||||
|
||||
| Surface | Риск |
|
||||
|---|---|
|
||||
| Compose ports on `0.0.0.0` | Вся поверхность API доступна на хосте |
|
||||
| Helm Ingress | Публичный HTTPS к Keystone/UI; другие OS-порты требуют явной экспозиции |
|
||||
| Read-only root FS (Helm) | Снижает write surface контейнера |
|
||||
|
||||
## TLS
|
||||
|
||||
- Compose: опциональный nginx TLS на `:443` с lab cert в `docker/tls/`
|
||||
- Helm: terminate TLS на Ingress + cert-manager (рекомендуется)
|
||||
|
||||
## Что не реализовано
|
||||
|
||||
- Реальная federation Keystone / семантика ротации Fernet keys
|
||||
- Паритет правил oslo.policy
|
||||
- Multi-tenant isolation beyond project_id filters в handlers
|
||||
|
||||
Считайте все данные одноразовыми lab fixtures.
|
||||
@@ -0,0 +1,30 @@
|
||||
**Language / Язык:** [English](../seed-profiles.md) | [Русский](seed-profiles.md)
|
||||
|
||||
# Seed-профили OpenStack
|
||||
|
||||
| Profile | Как загрузить | Содержимое |
|
||||
|---|---|---|
|
||||
| `minimal` | startup / `make seed` / `python -m app.openstack.seed_cli --profile minimal` | Default domain, admin+demo users, flavors, images, небольшой IaaS sample |
|
||||
| `demo` | `make seed-demo` / UI Data drawer / Helm `seed.profile=demo` / `--profile demo` | ~1000 servers, 16 hypervisors, 3 AZs, 5 projects, multi-net/SG topology, 600 volumes, ports/FIPs, Octavia/Heat/Ironic/Swift, nested pack samples |
|
||||
|
||||
Пароль для всех пользователей: **`secret`**. Домен: **`Default`**.
|
||||
|
||||
## Helm
|
||||
|
||||
```yaml
|
||||
seed:
|
||||
enabled: true
|
||||
profile: demo # or minimal
|
||||
```
|
||||
|
||||
Post-install Job запускает `python -m app.openstack.seed_cli`. Ручной reseed:
|
||||
|
||||
```bash
|
||||
kubectl exec deploy/<release>-openstack-api-simulator -- \
|
||||
python -m app.openstack.seed_cli --profile demo
|
||||
```
|
||||
|
||||
## Поведение
|
||||
|
||||
Оба профиля **очищают** лабораторные таблицы OpenStack и перезагружают данные.
|
||||
Предпочитайте `demo` для плотности / nested GET probes; `minimal` для быстрого CI.
|
||||
@@ -0,0 +1,55 @@
|
||||
**Language / Язык:** [English](../troubleshooting.md) | [Русский](troubleshooting.md)
|
||||
|
||||
# Устранение неполадок
|
||||
|
||||
## `/health/ready` возвращает 503
|
||||
|
||||
- Postgres не поднят или неверный `DATABASE_URL`
|
||||
- Миграции не применены — проверьте migrate initContainer / `make db-migrate`
|
||||
- Helm: `kubectl logs` на pod simulator (migrate init)
|
||||
|
||||
## Auth 401
|
||||
|
||||
- Неверный user/password/domain (`Default`)
|
||||
- Отсутствует project scope для project-scoped API
|
||||
- Токен от другого экземпляра simulator (reseed меняет ID)
|
||||
|
||||
## Пустые списки после lifecycle probe
|
||||
|
||||
Lifecycle DELETE может удалить demo-scoped строки. Перезагрузите:
|
||||
|
||||
```bash
|
||||
make seed-demo
|
||||
# or Helm:
|
||||
kubectl exec deploy/… -- python -m app.openstack.seed_cli --profile demo
|
||||
```
|
||||
|
||||
## Неверный сервис отвечает на порту
|
||||
|
||||
Проверьте gateway headers:
|
||||
|
||||
```bash
|
||||
curl -sI http://127.0.0.1:8774/ | grep -i openstack
|
||||
```
|
||||
|
||||
Ожидайте `X-OpenStack-Service: nova`. Если обращаетесь к simulator `:8080` напрямую,
|
||||
задайте `X-OpenStack-Route-Service` / `X-OpenStack-Service` сами.
|
||||
|
||||
## Helm port-forward на 5000 не работает
|
||||
|
||||
Forward **gateway** Service, а не simulator Service:
|
||||
|
||||
```bash
|
||||
kubectl port-forward svc/<release>-openstack-api-simulator-gateway 5000:5000
|
||||
```
|
||||
|
||||
## Pack activate 404 / пустые ops
|
||||
|
||||
Убедитесь, что `contracts/openstack/<series>/` есть в образе и
|
||||
`OPENSTACK_SERIES` — известное имя серии.
|
||||
|
||||
## Порты catalog недоступны клиенту
|
||||
|
||||
Catalog рекламирует per-service порты. При только Ingress на `:443→5000` Nova
|
||||
`:8774` не публикуется автоматически. Используйте port-forward или expose gateway
|
||||
Service (см. [kubernetes.md](kubernetes.md)).
|
||||
@@ -0,0 +1,31 @@
|
||||
**Language / Язык:** [English](../web-ui.md) | [Русский](web-ui.md)
|
||||
|
||||
# Web UI
|
||||
|
||||
Консоль обслуживается с Keystone/UI порта (**5000** на gateway).
|
||||
|
||||
| URL | Назначение |
|
||||
|---|---|
|
||||
| `/` или `/console` | Интерактивная консоль |
|
||||
| `/docs` | OpenAPI (simulator) |
|
||||
| `/ui/api/…` | UI JSON APIs |
|
||||
|
||||
## Environment drawer
|
||||
|
||||
- **OpenStack API pack** — список серий, активация пакета, переопределения microversion
|
||||
- Apply немедленно перемонтирует schema-маршруты
|
||||
|
||||
## Data drawer
|
||||
|
||||
- **Load demo cloud** — `POST /ui/api/demo/load` → `seed_openstack_demo`
|
||||
- **Unload / minimal** — сброс к minimal seed
|
||||
|
||||
## Брендинг
|
||||
|
||||
OpenStack red `#ED1C24`, console wordmark. Темы следуют общему chrome консоли
|
||||
(light/dark).
|
||||
|
||||
## Health
|
||||
|
||||
- `/health/live` — процесс работает
|
||||
- `/health/ready` — миграции применены + БД доступна
|
||||
@@ -0,0 +1,33 @@
|
||||
**Language / Язык:** [English](security.md) | [Русский](ru/security.md)
|
||||
|
||||
# Security
|
||||
|
||||
This project is a **laboratory simulator**, not a production OpenStack cloud.
|
||||
|
||||
## Trust boundary
|
||||
|
||||
- Default passwords (`secret`) are intentional for labs.
|
||||
- `TICKET_SIGNING_KEY` / `secret.ticketSigningKey` must be rotated before any
|
||||
shared or internet-facing deployment.
|
||||
- Bundled Postgres passwords in values/compose are lab defaults.
|
||||
|
||||
## Network exposure
|
||||
|
||||
| Surface | Risk |
|
||||
|---|---|
|
||||
| Compose ports on `0.0.0.0` | Entire API surface reachable on the host |
|
||||
| Helm Ingress | Public HTTPS to Keystone/UI; other OS ports need explicit exposure |
|
||||
| Read-only root FS (Helm) | Reduces container write surface |
|
||||
|
||||
## TLS
|
||||
|
||||
- Compose: optional nginx TLS on `:443` with lab cert under `docker/tls/`
|
||||
- Helm: terminate TLS at Ingress + cert-manager (recommended)
|
||||
|
||||
## What is not implemented
|
||||
|
||||
- Real Keystone federation / Fernet key rotation semantics
|
||||
- oslo.policy rule parity
|
||||
- Multi-tenant isolation beyond project_id filters in handlers
|
||||
|
||||
Treat all data as disposable lab fixtures.
|
||||
@@ -0,0 +1,30 @@
|
||||
**Language / Язык:** [English](seed-profiles.md) | [Русский](ru/seed-profiles.md)
|
||||
|
||||
# OpenStack seed profiles
|
||||
|
||||
| Profile | How to load | Contents |
|
||||
|---|---|---|
|
||||
| `minimal` | startup / `make seed` / `python -m app.openstack.seed_cli --profile minimal` | Default domain, admin+demo users, flavors, images, small IaaS sample |
|
||||
| `demo` | `make seed-demo` / UI Data drawer / Helm `seed.profile=demo` / `--profile demo` | ~1000 servers, 16 hypervisors, 3 AZs, 5 projects, multi-net/SG topology, 600 volumes, ports/FIPs, Octavia/Heat/Ironic/Swift, nested pack samples |
|
||||
|
||||
Password for all users: **`secret`**. Domain: **`Default`**.
|
||||
|
||||
## Helm
|
||||
|
||||
```yaml
|
||||
seed:
|
||||
enabled: true
|
||||
profile: demo # or minimal
|
||||
```
|
||||
|
||||
Post-install Job runs `python -m app.openstack.seed_cli`. Manual reseed:
|
||||
|
||||
```bash
|
||||
kubectl exec deploy/<release>-openstack-api-simulator -- \
|
||||
python -m app.openstack.seed_cli --profile demo
|
||||
```
|
||||
|
||||
## Behaviour
|
||||
|
||||
Both profiles **truncate** OpenStack lab tables then reload. Prefer `demo` for
|
||||
density / nested GET probes; `minimal` for fast CI.
|
||||
@@ -0,0 +1,55 @@
|
||||
**Language / Язык:** [English](troubleshooting.md) | [Русский](ru/troubleshooting.md)
|
||||
|
||||
# Troubleshooting
|
||||
|
||||
## `/health/ready` is 503
|
||||
|
||||
- Postgres not up or wrong `DATABASE_URL`
|
||||
- Migrations not applied — check migrate initContainer / `make db-migrate`
|
||||
- Helm: `kubectl logs` on the simulator pod (migrate init)
|
||||
|
||||
## Auth 401
|
||||
|
||||
- Wrong user/password/domain (`Default`)
|
||||
- Project scope missing for project-scoped APIs
|
||||
- Token from a different simulator instance (reseed rotates IDs)
|
||||
|
||||
## Empty lists after lifecycle probe
|
||||
|
||||
Lifecycle DELETE can remove demo-scoped rows. Reload:
|
||||
|
||||
```bash
|
||||
make seed-demo
|
||||
# or Helm:
|
||||
kubectl exec deploy/… -- python -m app.openstack.seed_cli --profile demo
|
||||
```
|
||||
|
||||
## Wrong service answers on a port
|
||||
|
||||
Confirm gateway headers:
|
||||
|
||||
```bash
|
||||
curl -sI http://127.0.0.1:8774/ | grep -i openstack
|
||||
```
|
||||
|
||||
Expect `X-OpenStack-Service: nova`. If you hit simulator `:8080` directly,
|
||||
set `X-OpenStack-Route-Service` / `X-OpenStack-Service` yourself.
|
||||
|
||||
## Helm port-forward to 5000 fails
|
||||
|
||||
Forward the **gateway** Service, not the simulator Service:
|
||||
|
||||
```bash
|
||||
kubectl port-forward svc/<release>-openstack-api-simulator-gateway 5000:5000
|
||||
```
|
||||
|
||||
## Pack activate 404 / empty ops
|
||||
|
||||
Ensure `contracts/openstack/<series>/` exists in the image and
|
||||
`OPENSTACK_SERIES` is a known series name.
|
||||
|
||||
## Client catalog ports unreachable
|
||||
|
||||
Catalog advertises per-service ports. With only Ingress on `:443→5000`, Nova
|
||||
`:8774` is not automatically published. Port-forward or expose the gateway
|
||||
Service (see [kubernetes.md](kubernetes.md)).
|
||||
@@ -0,0 +1,31 @@
|
||||
**Language / Язык:** [English](web-ui.md) | [Русский](ru/web-ui.md)
|
||||
|
||||
# Web UI
|
||||
|
||||
Console is served from the Keystone/UI port (**5000** on the gateway).
|
||||
|
||||
| URL | Purpose |
|
||||
|---|---|
|
||||
| `/` or `/console` | Interactive console |
|
||||
| `/docs` | OpenAPI (simulator) |
|
||||
| `/ui/api/…` | UI JSON APIs |
|
||||
|
||||
## Environment drawer
|
||||
|
||||
- **OpenStack API pack** — list series, activate pack, set microversion overrides
|
||||
- Apply remounts schema routes immediately
|
||||
|
||||
## Data drawer
|
||||
|
||||
- **Load demo cloud** — `POST /ui/api/demo/load` → `seed_openstack_demo`
|
||||
- **Unload / minimal** — reset to minimal seed
|
||||
|
||||
## Branding
|
||||
|
||||
OpenStack red `#ED1C24`, console wordmark. Themes follow the shared console
|
||||
chrome (light/dark).
|
||||
|
||||
## Health
|
||||
|
||||
- `/health/live` — process up
|
||||
- `/health/ready` — migrations applied + DB reachable
|
||||
Reference in New Issue
Block a user