End-to-end scenarios — zun — branch stable/2026.2
Branch
stable/2026.2@34135a563699— repository https://opendev.org/openstack/zun — analysed on 2026-11-01
Status codes and errors: 02-errors. Sources for each step: 01, 03, 05.
1. Create and run a container (Docker, Kuryr, one Cinder volume)
The default path. The scheduling runs **inside zun-api**, and the allocation is taken before any message reaches the node (zun/compute/api.py:55, zun/scheduler/filter_scheduler.py:49).
sequenceDiagram
autonumber
actor U as User
participant API as zun-api
participant DB as MariaDB
participant PL as Placement
participant NE as Neutron
participant CI as Cinder
participant MQ as RabbitMQ
participant C as zun-compute
participant RG as Registry or Glance
participant D as Docker and Kuryr
U->>API: POST /v1/containers?run=true
API->>NE: GET networks, ports, security groups (user token)
API->>DB: SELECT quota and usage counts
alt over quota
API-->>U: 403 OverQuota
end
API->>DB: INSERT container (Creating)
API->>CI: POST /volumes, when mount has size
API->>PL: GET /allocation_candidates
alt no candidate or filters reject all
API->>DB: UPDATE container (Error, not enough hosts)
API-->>U: 202, then status Error
else host chosen
API->>PL: PUT /allocations/uuid
API->>DB: INSERT container_actions (create)
API->>MQ: cast container_create, zun-compute.host
API-->>U: 202 Location
MQ->>C: container_create
C->>CI: GET volume status, each second up to 60 s
C->>CI: reserve, initialize_connection, attach
C->>C: os-brick connect, mkfs if needed, mount
C->>DB: claim, UPDATE compute_node, container.host
C->>RG: docker pull, or GET image file then docker load
C->>NE: POST /ports (admin, binding host)
C->>D: create_container, network_mode neutron-net-id
D->>NE: Kuryr binds the port
C->>D: start
C->>DB: UPDATE container (Running)
end
U->>API: GET /v1/containers/uuid
API->>MQ: call container_show
MQ->>C: container_show
C->>D: inspect
C-->>API: container
API-->>U: 200 RunningDiagnostics:
- 202 then
ErrorwithThere are not enough hosts available.: look inzun-apilogs forGot no allocation candidatesand atGET /v1/servicesfor a down node (zun/scheduler/client/query.py:74). - Stuck in
Creating, emptyhost:zun-computeon the target did not take the message, or it died; on restart it goes toError(zun/compute/manager.py:99). No time-out exists on the API side. Error,Volumes did not reach available status: Cinder is slow or the volume is in use (zun/compute/manager.py:221).Error, image message,hostkept: pull failed (zun/compute/manager.py:346). Placement allocation is still held [inferred].Error, Docker message,hostcleared: Kuryr or Docker refused; look atkuryr-libnetworklogs (zun/compute/manager.py:378).
2. Create a capsule (CRI, CNI)
sequenceDiagram
autonumber
actor U as User
participant API as zun-api
participant DB as MariaDB
participant PL as Placement
participant C as zun-compute
participant NE as Neutron
participant CD as containerd
participant CN as zun-cni
participant DM as zun-cni-daemon
U->>API: POST /v1/capsules with template
API->>DB: INSERT capsule and member containers
API->>PL: GET /allocation_candidates, PUT /allocations
API->>C: cast container_create (run false)
API-->>U: 202
C->>NE: POST /ports (binding host)
C->>DB: UPDATE cni_metadata (VIF)
C->>CD: RunPodSandbox, runtime handler
CD->>CN: CNI ADD
CN->>DM: POST addNetwork
DM->>DB: read cni_metadata
DM->>DM: plug VIF with os-vif, configure namespace
loop up to 60 s, each second
DM->>NE: GET ports by host
end
alt port active
DM-->>CN: 202 and VIF
CN-->>CD: result
CD-->>C: sandbox id
C->>CD: PullImage, CreateContainer, StartContainer for init containers, then wait
C->>CD: PullImage, CreateContainer, StartContainer for containers
C->>DB: UPDATE capsule
else timeout
DM-->>CN: 500 (RetryError)
CN-->>CD: error code
C->>DB: UPDATE capsule (Error)
endSources: zun/container/cri/driver.py:49, zun/container/cri/driver.py:72, zun/cni/daemon/service.py:57, zun/cni/plugins/zun_cni_registry.py:72.
Diagnostics: 500 from the daemon, with RetryError in its log (02 T21): the Neutron agent or OVN did not make the port active within vif_active_timeout. With Kata, runtime_handler must match the containerd runtime name (zun/container/cri/driver.py:74), and container_runtime must name it; the default handler is used for runc (zun/container/cri/driver.py:75).
3. Delete a container
sequenceDiagram
autonumber
actor U as User
participant API as zun-api
participant MQ as RabbitMQ
participant C as zun-compute
participant D as Docker
participant NE as Neutron
participant CI as Cinder
participant PL as Placement
participant DB as MariaDB
U->>API: DELETE /v1/containers/id
alt status not allowed
API-->>U: 409 InvalidStateException
else node down
API-->>U: 500 ContainerHostNotUp, message obfuscated
else no host recorded
API->>DB: DELETE container
API-->>U: 204
else placed
API->>MQ: cast container_delete
API-->>U: 204
MQ->>C: container_delete
C->>NE: disconnect, delete or unbind port
C->>NE: delete security group zun-uuid when ports exposed
C->>D: remove_container
C->>CI: begin_detaching, terminate_connection, detach
C->>CI: DELETE volume when auto_remove, poll up to 60 s
C->>DB: release usage
C->>PL: PUT empty allocation
C->>DB: DELETE container
endDiagnostics: row present after a 204 with Error: Docker refused and force was not set (zun/compute/manager.py:556). Cinder volume in detaching: roll_detaching is called on disconnect errors (zun/volume/cinder_workflow.py:166).
4. Interactive session (exec)
sequenceDiagram
autonumber
actor U as Client
participant API as zun-api
participant C as zun-compute
participant D as Docker on the node
participant WS as zun-wsproxy
participant DB as MariaDB
U->>API: POST /v1/containers/id/execute?run=false&interactive=true
API->>C: call container_exec
C->>D: exec_create
C->>DB: INSERT exec_instance (exec_id, url, token)
C-->>API: exec_id, token
API-->>U: 200 proxy_url with token, uuid and exec_id
U->>WS: WebSocket GET proxy_url
WS->>DB: SELECT container, exec_instances (admin)
alt token or exec_id wrong
WS-->>U: InvalidWebsocketToken, connection closed
else valid
WS->>D: exec_start over tcp 2375, socket
U-->>D: bytes both ways through the proxy
end
U->>API: POST execute_resize?exec_id, h, wSources: zun/compute/manager.py:826, zun/compute/api.py:175, zun/websocket/websocketproxy.py:238.
Diagnostics: connection refused at the last step: Docker does not listen on docker_remote_api_url, or a firewall stands between the proxy and port 2375. Origin header does not match this host: add the host to [websocket_proxy]/allowed_origins (zun/websocket/websocketproxy.py:268). This is the case for a console opened from Skyline on another origin.
5. Node loses Docker state (sync and healing)
sequenceDiagram
autonumber
participant T as Timer 60 s
participant C as zun-compute
participant DB as MariaDB
participant D as Docker
T->>C: sync_container_state
C->>DB: SELECT all containers and capsules
C->>D: list_containers
C->>DB: SELECT rows for this host and for UUIDs in Docker
loop containers in both
alt status differs and no task
C->>DB: UPDATE status
end
end
loop containers on this host, not in Docker
alt auto_remove
C->>DB: UPDATE status Deleted
Note over C: next delete_unused_containers removes it
else auto_heal and rebuildable
C--xC: container_rebuild call fails, missing argument
Note over C: warning logged, nothing rebuilt
else
C->>DB: UPDATE status Error, No such container
end
endSources: zun/compute/manager.py:1237, zun/container/docker/driver.py:545, zun/container/docker/driver.py:506.
Diagnostics: a container flips to Error with No such container after a Docker data loss. auto_heal does not repair it because of the bug at zun/container/docker/driver.py:518, and the warning heal container with rebuilding failed is the only trace.
6. Node inventory and scheduling loop
sequenceDiagram
autonumber
participant C as zun-compute
participant D as Docker and host
participant DB as MariaDB
participant PL as Placement
participant API as zun-api
loop at most every 60 s
C->>D: info, /proc, disk usage
C->>DB: UPDATE compute_node
C->>DB: UPDATE zun_service.last_seen_up
opt resources changed
C->>PL: PUT inventories, traits, aggregates
end
end
API->>DB: read compute_node, zun_service, for a request
API->>PL: GET /allocation_candidates
Note over API: AvailabilityZoneFilter, ComputeFilter, RuntimeFilterSources: zun/compute/manager.py:1179, zun/compute/compute_node_tracker.py:61, zun/scheduler/filter_scheduler.py:49, zun/conf/scheduler.py:64.
Diagnostics: Placement counts VCPU as whole units per container, so a 0.1-CPU container takes one VCPU there (zun/scheduler/utils.py:298, zun/scheduler/utils.py:301). A node "full" in Placement may look idle in docker stats. Raise allocation_ratio to compensate. Disk is claimed only when disk is set (zun/scheduler/utils.py:286).
Source: reverse-spec-zun/04-scenarios_stable-2026.2.md. The _rewrite/ and _inventory/ files are not published on the site.