This work is licensed under a Creative Commons Attribution 3.0 Unported License. http://creativecommons.org/licenses/by/3.0/legalcode

Secondary Zones

Outline support for Secondary Zones concept in Designate.

Terminology

Term Meaning
axfr Full Zone Update (AXFR)
zone Seconday Zone - Zone that transfers it’s state / data from a given set of masters

Problem description

We want to support Secondary Zones in order to lay the grounds for higher level features like incoming (A|I)XFR, Federation and others (will be separate specs).

Proposed change

We introduce a new concept of a Secondary zone within Designate that has external Masters. In term this means that Designate will be acting as a Slave.

In MiniDNS we add support for inbound AXFR and NOTIFY.

In terms of Pools a Secondary Zone would be placed equally as a Primary

API Changes

API endpoints for recordsets should disallow any Create, Update, Delete action.

status fields will be the same as with Primary Zones.

New Zone parameters

Parameter Type Required Default Description
type ENUM(PRIMARY, SECONDARY) No false Primary or Secondary
masters List No None Zone Masters
transferred_at Datetime
None Last successful transfer

Create Secondary Zone

When creating a new zone the managed_resource_email is used as the initial email.

The fields version will be 1 since it’s not yet transferred and transferred_at as null.

POST /v2/zones HTTP/1.1
Host: 127.0.0.1:9001
Accept: application/json
Content-Type: application/json

{
  "zone": {
    "name": "example.org.",
    "description": "This is an example zone.",
    "masters": ["10.0.0.1", "10.0.0.2:5354"],
    "type": "SECONDARY",
  }
}
HTTP/1.1 201 Created
Content-Type: application/json

{
  "zone": {
    "id": "a86dba58-0043-4cc6-a1bb-69d5e86f3ca3",
    "pool_id": "572ba08c-d929-4c70-8e42-03824bb24ca2",
    "project_id": "4335d1f0-f793-11e2-b778-0800200c9a66",
    "name": "example.org.",
    "email": "managed@foo.co",
    "serial": 1404757531,
    "status": "ACTIVE",
    "description": "This is an example zone.",
    "masters": ["10.0.0.1", "10.0.0.2:5354"],
    "type": "SECONDARY",
    "transferred_at": null,
    "version": 1,
    "created_at": "2014-07-07T18:25:31.275934",
    "updated_at": null,
    "links": {
      "self": "https://127.0.0.1:9001/v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3"
    }
  }
}

Get Secondary Zone

Retrieves a secondary zone with the specified ID.

Example of GET on a untransferred zone:

GET /v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3 HTTP/1.1
Host: 127.0.0.1:9001
Accept: application/json
Content-Type: application/json
HTTP/1.1 200 OK
Vary: Accept
Content-Type: application/json

{
  "zone": {
    "id": "a86dba58-0043-4cc6-a1bb-69d5e86f3ca3",
    "pool_id": "572ba08c-d929-4c70-8e42-03824bb24ca2",
    "project_id": "4335d1f0-f793-11e2-b778-0800200c9a66",
    "name": "example.org.",
    "email": "managed@foo.co",
    "serial": 1404757531,
    "status": "ACTIVE",
    "description": "This is an example zone.",
    "masters": ["10.0.0.1", "10.0.0.2:5354"],
    "type": "SECONDARY",
    "transferred_at": null,
    "version": 1,
    "created_at": "2014-07-07T18:25:31.275934",
    "updated_at": null,
    "links": {
      "self": "https://127.0.0.1:9001/v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3"
    }
  }
}

List Secondary Zones

To filter on zone type do type=<PRIMARY|SECONDARY> as query parameters.

Below there is examples of a Zone that’s not transferred yet and one that is.

GET /v2/zones?type=SECONDARY HTTP/1.1
Host: 127.0.0.1:9001
Accept: application/json
Content-Type: application/json
HTTP/1.1 200 OK
Vary: Accept
Content-Type: application/json

{
  "zones": [{
    "id": "a86dba58-0043-4cc6-a1bb-69d5e86f3ca3",
    "pool_id": "572ba08c-d929-4c70-8e42-03824bb24ca2",
    "project_id": "4335d1f0-f793-11e2-b778-0800200c9a66",
    "name": "example.org.",
    "email": "managed@foo.co",
    "serial": 2014120100,
    "status": "ACTIVE",
    "description": "This is an example zone.",
    "masters": ["10.0.0.1", "10.0.0.2:5354"],
    "type": "SECONDARY",
    "transferred_at": "2014-07-07T18:25:31.275934",
    "version": 2,
    "created_at": "2014-07-07T18:25:31.275934",
    "updated_at": "2014-07-07T18:25:31.275934",
    "links": {
      "self": "https://127.0.0.1:9001/v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3"
    }
  }, {
    "id": "fdd7b0dc-52a3-491e-829f-41d18e1d3ada",
    "pool_id": "572ba08c-d929-4c70-8e42-03824bb24ca2",
    "project_id": "4335d1f0-f793-11e2-b778-0800200c9a66",
    "name": "example.net.",
    "email": "managed@foo.co",
    "serial": 1404756682,
    "status": "ACTIVE",
    "description": "This is another example zone.",
    "masters": ["10.0.0.1", "10.0.0.2:5354"],
    "type": "SECONDARY",
    "transferred_at": null,
    "version": 1,
    "created_at": "2014-07-07T18:22:08.287743",
    "updated_at": null,
    "links": {
      "self": "https://127.0.0.1:9001/v2/zones/fdd7b0dc-52a3-491e-829f-41d18e1d3ada"
    }
  }],
  "links": {
    "self": "https://127.0.0.1:9001/v2/zones"
  }
}

Update a Secondary Zone

Changes the specified attribute(s) for an existing zone.

In the example below, we update one of the masters to 10.0.0.3.

NOTE: In terms of a Secondary Zone only the following fields below are editable.

Parameter Description
description Description of Zone
masters Master servers
PATCH /v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3 HTTP/1.1
Host: 127.0.0.1:9001
Accept: application/json
Content-Type: application/json

{
  "zone": {
    "masters": ["10.0.0.1", 10.0.0.3:1053"]
  }
}
HTTP/1.1 200 OK
Content-Type: application/json

{
  "zone": {
    "id": "a86dba58-0043-4cc6-a1bb-69d5e86f3ca3",
    "pool_id": "572ba08c-d929-4c70-8e42-03824bb24ca2",
    "project_id": "4335d1f0-f793-11e2-b778-0800200c9a66",
    "name": "example.org.",
    "serial": 0,
    "status": "ACTIVE",
    "description": "This is an example zone.",
    "masters": ["10.0.0.1", "10.0.0.3:1053"],
    "type": "SECONDARY",
    "transferred_at": "2014-07-07T18:25:31.275934",
    "version": 1,
    "created_at": "2014-07-07T18:25:31.275934",
    "updated_at": null,
    "links": {
      "self": "https://127.0.0.1:9001/v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3"
    }
  }
}

Delete Secondary Zone

DELETE /v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3 HTTP/1.1
Host: 127.0.0.1:9001
HTTP/1.1 204 No Content

Central Changes

Disallow changing of a zone from PRIMARY <> SECONDARY.

Add a periodic task that loops over secondary zones looking at their transferred_at and does a call to MDNS to trigger a new AXFR to keep the zone updated.

Storage Changes

Modify Table - domains

Column Type Nullable? Unique? Notes Action
type EMUM(PRIMARY, SECONDARY) No No Zone type add
transferred_at DATETIME Yes (Not transferred) No Last transfer at add

New Table - domain_attributes

A new table to store any metadata / attributes that doesn’t need to be on the on the domains table.

An index across domain_id, key, value.

Column Type Nullable? Unique? Notes Action
id UUID no Yes ID for this attribute add
domain_id FK to Domain UUID no No Domain ID this attribute belongs to add
key ENUM(masters) no No Zone type add
value VARCHAR no No Master servers for Zone add

MiniDNS Changes

Zone Creation

When a zone is created currently a notification is sent to mdns, we’ll plugin here and do a AXFR if zone.type is SECONDARY.

NOTIFY

We need to change __call__ to pass NOTIFY down to self._handle_notify().

  1. Receives a NOTIFY
  2. Query the SOURCE of the NOTIFY for SOA
  3. Compare response serial vs local if it doesn’t match then continue to next step.
  4. Do a AXFR towards the server that sent the NOTIFY.
  5. Call dnsutils.from_dnspython to get Domain a’la Designate version
  6. Call Central to method with the data from #5 to update the domain.

New - RequestHandler._handle_notify(context, request)

Handles a Notification and eventually hands off to do a AXFR.

Parameter Description Required
context Security context information. Yes
request The DNS request Yes

New - Service.zone_sync(context, zone, master_addr=None)

A method utilized by any method in MDNS that needs to do a AXFR.

Parameter Description Required
context Security context information. Yes
zone A objects.Domain object Yes
master_addr Address to use for the AXFR No

Future work

The below is out of scope for this.

  • A task for /zones/<id>/tasks or so should be added in the future to allow a “forced” AXFR via the API.
  • A task to switch from a SECONDARY > PRIMARY.

Implementation

Assignee(s)

Primary assignee:
<https://launchpad.net/~endre-karlson>

Milestones

Target Milestone for completion:
Kilo-1

Work Items

  • Add new columns to storage
  • Extend Zones API to allow CRUD for Secondary Zones
  • Extend Central logic to check if it’s a Master / Secondary Zone.

Dependencies