OpenKeel: the sovereign French Cloud solution of the inherent group, with a European reach Discover inherent

Reverse-spec · Services

zun — Scenarios

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 Running

Diagnostics:

  • 202 then Error with There are not enough hosts available.: look in zun-api logs for Got no allocation candidates and at GET /v1/services for a down node (zun/scheduler/client/query.py:74).
  • Stuck in Creating, empty host: zun-compute on the target did not take the message, or it died; on restart it goes to Error (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, host kept: pull failed (zun/compute/manager.py:346). Placement allocation is still held [inferred].
  • Error, Docker message, host cleared: Kuryr or Docker refused; look at kuryr-libnetwork logs (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)
  end

Sources: 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
  end

Diagnostics: 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, w

Sources: 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
  end

Sources: 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, RuntimeFilter

Sources: 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.