End-to-end scenarios — designate — branch stable/2026.2
Branch
stable/2026.2@e3dd774db145— repository https://opendev.org/openstack/designate — analysed on 2026-10-29
The scenarios assume one pool whose targets are PowerDNS servers (pdns4 driver) configured as secondaries of designate-mdns, and a tooz backend. Statuses and errors refer to errors; triggers to async processing.
1. Creating a primary zone
The API answers 202 as soon as the zone, its SOA and its NS recordsets are in the database. The zone becomes ACTIVE only when every pool nameserver serves its serial.
sequenceDiagram
autonumber
actor U as User
participant API as designate-api
participant C as designate-central
participant DB as MariaDB
participant W as designate-worker
participant P as PowerDNS (pool target)
participant M as designate-mdns
U->>API: POST /v2/zones {"name":"example.org.","email":"…"}
API->>C: AMQP call create_zone(zone)
C->>C: policy create_zone, quota, name/TLD/blacklist, ownership, scheduler → pool
alt invalid name, quota, collision
C-->>API: InvalidZoneName 400 / OverQuota 413 / DuplicateZone 409 / IllegalChildZone 403
API-->>U: error JSON
end
C->>DB: INSERT zones (CREATE, PENDING), recordsets/records SOA + NS (managed)
C->>W: AMQP cast create_zone(zone)
C-->>API: zone
API-->>U: 202 {status: PENDING, action: CREATE}
W->>P: POST /api/v1/servers/localhost/zones {kind: slave, masters: [mdns:5354]}
W->>P: DNS NOTIFY example.org. SOA
P->>M: DNS SOA query, then AXFR example.org. (TCP 5354)
M->>DB: SELECT recordsets/records of the zone
M-->>P: SOA, NS, …, SOA
W->>W: sleep poll_delay (5 s)
loop until every nameserver serves serial ≥ zone.serial (≤ 10 tries, 15 s apart)
W->>P: DNS SOA query example.org.
end
alt threshold met
W->>C: AMQP cast update_status(SUCCESS, serial, CREATE)
C->>DB: UPDATE zones/records SET action=NONE, status=ACTIVE
else backend error or nameservers late
W->>C: AMQP cast update_status(ERROR or NO_ZONE)
C->>DB: UPDATE zones SET status=ERROR
end
U->>API: GET /v2/zones/{id} (polling)Diagnostics: NoServersConfigured (500) means designate-manage pool update was not run (step 3). A zone stuck in PENDING with no worker log means the cast was lost: worker_periodic_recovery re-sends it after 455 s. A zone in ERROR right after creation points to the backend (step 8, worker log Failed to CREATE zone_name=…); in ERROR after a few minutes, to the AXFR between PowerDNS and mdns (mdns log Unknown TSIG key, firewall on 5354) or to the NOTIFY.
2. Adding a recordset (serial batching)
sequenceDiagram
autonumber
actor U as User
participant API as designate-api
participant C as designate-central
participant DB as MariaDB
participant PR as designate-producer
participant W as designate-worker
participant P as DNS servers
U->>API: POST /v2/zones/{id}/recordsets {"name":"www.example.org.","type":"A","records":["192.0.2.1"]}
API->>C: call create_recordset
C->>C: lock zone-<id>; policy create_recordset; quotas; placement and record checks
C->>DB: INSERT recordsets, records (CREATE, PENDING, serial=now)
C->>DB: UPDATE zones SET action=UPDATE, status=PENDING, increment_serial=1
API-->>U: 202 {status: PENDING}
Note over PR: every 5 s (increment_serial task, own shard range)
PR->>C: call find_zones(increment_serial=1, shard BETWEEN …)
PR->>C: call increment_zone_serial(zone)
C->>DB: UPDATE zones SET serial=<unix time>, increment_serial=0; UPDATE SOA record
PR->>W: cast update_zone(zone)
W->>P: backend update (no-op for pdns4) + DNS NOTIFY
P->>P: AXFR from mdns
W->>P: SOA polling
W->>C: cast update_status(SUCCESS, serial, UPDATE)
C->>DB: UPDATE records SET status=ACTIVE WHERE serial <= reported serialDiagnostics: changes made within the same 5 s window share one serial and one push. If the recordset stays PENDING, check that a producer owns the zone's shard (GET /v2/service_statuses, tooz group) — without any producer, serial increments never happen and nothing is pushed.
3. Deleting a zone
sequenceDiagram
autonumber
actor U as User
participant API as designate-api
participant C as designate-central
participant DB as MariaDB
participant W as designate-worker
participant P as DNS servers
participant PR as designate-producer
U->>API: DELETE /v2/zones/{id}
API->>C: call delete_zone
alt sub-zones exist / zone shared
C-->>U: 400 zone_has_sub_zone / zone_is_shared
end
C->>DB: UPDATE zones SET action=DELETE, status=PENDING
C->>W: cast delete_zone(zone, hard_delete)
API-->>U: 202 {action: DELETE, status: PENDING}
W->>P: DELETE /api/v1/servers/localhost/zones/example.org.
loop until no nameserver answers for the zone (serial 0)
W->>P: DNS SOA query
end
W->>C: cast update_status(SUCCESS, 0, DELETE)
C->>DB: UPDATE zones SET status=DELETED, deleted=<id>, deleted_at=now
U->>API: GET /v2/zones/{id} → 404
Note over PR: 7 days later, zone_purge
PR->>C: call purge_zones(deleted != 0, deleted_at <= now-604800)
C->>DB: DELETE FROM zones (re-parent children)Diagnostics: a DNS server that answers with recursion for a deleted zone used to keep the zone in PENDING/ERROR; since 26d9b96afaa7 a non-authoritative answer with RA counts as "no zone" (history). Heat and Neutron consider a zone deleted on the 404 (step 13).
4. Secondary zone and NOTIFY from an external master
sequenceDiagram
autonumber
actor U as User
participant API as designate-api
participant C as designate-central
participant W as designate-worker
participant MA as External master
participant M as designate-mdns
participant P as DNS servers
U->>API: POST /v2/zones {"name":"sec.example.","type":"SECONDARY","masters":["203.0.113.5"]}
API->>C: call create_zone (serial = 1, email = managed_resource_email)
C->>W: cast create_zone
C->>W: cast perform_zone_xfr
W->>MA: DNS AXFR sec.example. (xfr_timeout 10 s)
W->>C: call update_zone(zone with recordsets, increment_serial=False)
W->>P: create slave zone + NOTIFY; P AXFRs from mdns
MA->>M: DNS NOTIFY sec.example.
M->>M: zone found, sender is a master
M->>MA: DNS SOA query
alt master serial != stored serial
M->>W: cast perform_zone_xfr(zone, [master])
end
M-->>MA: NOTIFY response (AA)Diagnostics: NOTIFY from another address is refused (mdns log NOTIFY for … from non-master server). Without NOTIFY, the producer's periodic_secondary_refresh checks the master at most hourly.
5. Floating IP PTR record (Skyline "Reverse DNS", openstack ptr record set)
sequenceDiagram
autonumber
actor U as User
participant API as designate-api
participant C as designate-central
participant N as Neutron
participant DB as MariaDB
participant W as designate-worker
U->>API: PATCH /v2/reverse/floatingips/RegionOne:{fip} {"ptrdname":"host.example.org."}
API->>C: call update_floatingip
C->>C: policy set_floatingip_reverse
C->>N: GET /v2.0/floatingips?project_id=<project> (user token)
alt FIP not in the list
C-->>U: 404 FloatingIP … is not associated for project
end
C->>DB: find zone 2.0.192.in-addr.arpa. owned by managed_resource_tenant_id
opt missing
C->>C: create_zone (managed tenant, managed_resource_email) → worker push
end
C->>DB: create or update managed PTR recordset 10.2.0.192.in-addr.arpa. (managed_resource_type ptr:floatingip)
C->>W: (via the zone update) push
API-->>U: 202 {ptrdname, status: PENDING}Diagnostics: 409 duplicate_zone means another project owns a zone with the reverse zone's name (protection added in e3dd774db145). 504 neutron_communication_failure means Neutron failed or no endpoint was found.
6. Neutron port or floating IP with a DNS name (Neutron's external DNS driver)
Neutron's Designate driver calls the API with the user's token for the forward record and with its own admin credentials (edit_managed) for the PTR (neutron:neutron/services/externaldns/drivers/designate/driver.py:38).
sequenceDiagram
autonumber
participant N as neutron-server
participant API as designate-api
N->>API: GET /v2/zones?name=example.org. (user token, resolve by name)
N->>API: POST /v2/zones/{id}/recordsets {name: "vm1.example.org.", type: A, records: [IP]}
alt 404
API-->>N: DNSDomainNotFound
else 409
API-->>N: DuplicateRecordSet
else 413
API-->>N: ExternalDNSOverQuota
end
opt allow_reverse_dns_lookup
N->>API: GET /v2/zones?name=<in-addr zone> (admin client)
N->>API: POST /v2/zones/{id}/recordsets PTR (admin, X-Designate-Edit-Managed-Records)
alt 404: zone missing
N->>API: POST /v2/zones {name: <in-addr zone>, email: admin@<domain>} (409 ignored)
N->>API: POST …/recordsets PTR
end
endThe sink path (Nova compute.instance.create.end, Neutron floatingip.update.end → create_managed_records) is the alternative integration; it does not involve the API (async).
7. Zone import
sequenceDiagram
autonumber
actor U as User
participant API as designate-api
participant C as designate-central
participant T as central import thread
U->>API: POST /v2/zones/tasks/imports (Content-Type text/dns, zone file)
API->>C: call create_zone_import(body)
C->>C: INSERT zone_tasks (IMPORT, PENDING); start thread
API-->>U: 202 {status: PENDING}
T->>T: dnspython parse ($ORIGIN, SOA required)
alt parse error
T->>C: update_zone_import(ERROR, "Malformed zonefile.")
else ok
T->>C: create_zone(zone + recordsets) — same path as scenario 1
T->>C: update_zone_import(COMPLETE, zone_id)
end
U->>API: GET /v2/zones/tasks/imports/{id} (polling)Source: reverse-spec-designate/04-scenarios_stable-2026.2.md. The _rewrite/ and _inventory/ files are not published on the site.