Development Environment on Ubuntu

Designate is comprised of four main components Designate API, Designate Central, designate-mdns, and designate-pool-manager, supported by a few standard open source components. For more information see Architecture.

There are many different options for customizing Designate, and two of these options have a major impact on the installation process:

  • The storage backend used (SQLite or MySQL)
  • The DNS backend used (PowerDNS or BIND9)

This guide will walk you through setting up a typical development environment for Designate, using BIND9 as the DNS backend and MySQL as the storage backend. For a more complete discussion on installation & configuration options, please see Architecture.

For this guide you will need access to an Ubuntu Server (16.04).

Development Environment

Installing Designate

  1. Install system package dependencies (Ubuntu)
$ sudo apt update
$ sudo apt install -y python-pip python-virtualenv libssl-dev libffi-dev git
$ sudo apt build-dep -y python-lxml
  1. Clone the Designate repo
$ mkdir openstack
$ cd openstack
$ git clone https://git.openstack.org/openstack/designate.git
$ cd designate
  1. Setup a virtualenv

Note

This step is necessary to allow the installation of an up-to-date pip, independent of the version packaged for Ubuntu. it is also useful in isolating the remainder of Designate’s dependencies from the rest of the system.

$ virtualenv .venv
$ . .venv/bin/activate
  1. Install an up-to-date pip
$ pip install -U pip
  1. Install Designate and its dependencies
$ pip install -e .
  1. Change directories to the etc/designate folder.

Note

Everything from here on out should take place in or below your designate/etc folder

$ cd etc/designate
  1. Create Designate’s config files by copying the sample config files
$ cp -a rootwrap.conf.sample rootwrap.conf
  1. Make the directory for Designate’s state files
$ mkdir -p ../../state

Configuring Designate

Create the designate.conf file

$ editor designate.conf

Copy or mirror the configuration from this sample file here:

[DEFAULT]
########################
## General Configuration
########################
# Show debugging output in logs (sets DEBUG log level output)
debug = True

# Top-level directory for maintaining designate's state.
state_path = $pybasedir/state

# Driver used for issuing notifications
notification_driver = messaging

# Use "sudo designate-rootwrap /etc/designate/rootwrap.conf" to use the real
# root filter facility.
# Change to "sudo" to skip the filtering and just run the command directly
# root_helper = sudo

# Supported record types
#supported_record_type = A, AAAA, CNAME, MX, SRV, TXT, SPF, NS, PTR, SSHFP, SOA

# RabbitMQ Config
rabbit_userid = designate
rabbit_password = designate
#rabbit_virtual_host = /
#rabbit_use_ssl = False
#rabbit_hosts = 127.0.0.1:5672

########################
## Service Configuration
########################
#-----------------------
# Central Service
#-----------------------
[service:central]
# Maximum domain name length
#max_domain_name_len = 255

# Maximum record name length
#max_record_name_len = 255

#-----------------------
# API Service
#-----------------------
[service:api]
# Address to bind the API server
api_host = 0.0.0.0

# Port to bind the API server
api_port = 9001

# Authentication strategy to use - can be either "noauth" or "keystone"
auth_strategy = noauth

# Enable API Version 1
enable_api_v1 = True

# Enabled API Version 1 extensions
enabled_extensions_v1 = diagnostics, quotas, reports, sync, touch

# Enable API Version 2
enable_api_v2 = True

# Enabled API Version 2 extensions
enabled_extensions_v2 = quotas, reports

#-----------------------
# mDNS Service
#-----------------------
[service:mdns]
#workers = None
#host = 0.0.0.0
#port = 5354
#tcp_backlog = 100

#-----------------------
# Worker Service
#-----------------------
[service:worker]
# Whether to send events to worker instead of Pool Manager
enabled = True
#workers = None
#threads = 1000
#threshold_percentage = 100
#poll_timeout = 30
#poll_retry_interval = 15
#poll_max_retries = 10
#poll_delay = 5
notify = True

#-----------------------
# Producer Service
#-----------------------
[service:producer]
#workers = None
#threads = 1000
#enabled_tasks = None
#export_synchronous = True

#------------------------
# Deleted domains purging
#------------------------
[producer_task:domain_purge]
#interval = 3600  # 1h
#batch_size = 100
#time_threshold = 604800  # 7 days

#------------------------
# Delayed zones NOTIFY
#------------------------
[producer_task:delayed_notify]
#interval = 5

#------------------------
# Worker Periodic Recovery
#------------------------
[producer_task:worker_periodic_recovery]
#interval = 120

########################
## Storage Configuration
########################
#-----------------------
# SQLAlchemy Storage
#-----------------------
[storage:sqlalchemy]
# Database connection string - to configure options for a given implementation
# like sqlalchemy or other see below
connection = mysql+pymysql://root:password@127.0.0.1/designate?charset=utf8
#connection_debug = 100
#connection_trace = True
#sqlite_synchronous = True
#idle_timeout = 3600
#max_retries = 10
#retry_interval = 10

Installing RabbitMQ

Install the RabbitMQ package

$ sudo apt install -y rabbitmq-server

Create a user:

$ sudo rabbitmqctl add_user designate designate

Give the user access to the / vhost:

$ sudo rabbitmqctl set_permissions -p "/" designate ".*" ".*" ".*"

Installing MySQL

Install the MySQL server package

$ sudo apt install -y mysql-server

If you do not have MySQL previously installed, you will be prompted to change the root password. By default, the MySQL root password for Designate is “password”. You can:

  • Change the root password to “password”

  • If you want your own password, edit the designate.conf file and change any instance of

    “mysql+pymysql://root:password@127.0.0.1/designate?charset=utf8” to “mysql+pymysql://root:YOUR_PASSWORD@127.0.0.1/designate?charset=utf8”

You can change your MySQL password anytime with the following command:

$ mysqladmin -u root -p password NEW_PASSWORD
Enter password <enter your old password>

Create the Designate tables

$ mysql -u root -p
Enter password: <enter your password here>

mysql> CREATE DATABASE `designate` CHARACTER SET utf8 COLLATE utf8_general_ci;
mysql> exit;

Install additional packages

$ sudo apt install -y libmysqlclient-dev
$ pip install pymysql

Installing BIND9

Install the DNS server, BIND9

$ sudo apt install -y bind9

Update the BIND9 Configuration

$ sudo editor /etc/bind/named.conf.options

Change the corresponding lines in the config file:

options {
  directory "/var/cache/bind";
  dnssec-validation auto;
  auth-nxdomain no; # conform to RFC1035
  listen-on-v6 { any; };
  allow-new-zones yes;
  request-ixfr no;
  recursion no;
};

Disable AppArmor for BIND9

$ sudo touch /etc/apparmor.d/disable/usr.sbin.named
$ sudo systemctl reload apparmor

Restart BIND9:

$ sudo systemctl restart bind9

Create and Import pools.yaml File

Create the pools.yaml file

$ editor pools.yaml

Copy or mirror the configuration from this sample file here:

- name: default
  # The name is immutable. There will be no option to change the name after
  # creation and the only way will to change it will be to delete it
  # (and all zones associated with it) and recreate it.
  description: Default BIND9 Pool

  attributes: {}

  # List out the NS records for zones hosted within this pool
  ns_records:
    - hostname: ns1-1.example.org.
      priority: 1

  # List out the nameservers for this pool. These are the actual BIND servers.
  # We use these to verify changes have propagated to all nameservers.
  nameservers:
    - host: 127.0.0.1
      port: 53

  # List out the targets for this pool. For BIND, most often, there will be one
  # entry for each BIND server.
  targets:
    - type: bind9
      description: BIND9 Server 1

      # List out the designate-mdns servers from which BIND servers should
      # request zone transfers (AXFRs) from.
      masters:
        - host: 127.0.0.1
          port: 5354

      # BIND Configuration options
      options:
        host: 127.0.0.1
        port: 53
        rndc_host: 127.0.0.1
        rndc_port: 953
        rndc_key_file: /etc/bind/rndc.key

  # Optional list of additional IP/Port's for which designate-mdns will send
  # DNS NOTIFY packets to
  # also_notifies:
  #  - host: 192.0.2.4
  #    port: 53

Initialize the Database

Sync the Designate database.

$ designate-manage database sync

Start the Central Service

Start the central service.

$ designate-central

You’ll now be seeing the log from the central service.

Initialize Pools Information

Import the pools.yaml file into Designate. It is important that designate-central is started before invoking this command

$ designate-manage pool update --file pools.yaml

Start the other Services

Open up some new ssh windows and log in to your server (or open some new screen/tmux sessions).

$ cd openstack/designate
$ source .venv/bin/activate

Start the other services

$ designate-api
$ designate-mdns
$ designate-worker
$ designate-producer

You’ll now be seeing the logs from the other services.

Exercising the API

Note

If you have a firewall enabled, make sure to open port 53, as well as Designate’s default port (9001).

Using a web browser, curl statement, or a REST client, calls can be made to the Designate API. You can find the various API calls on the api-ref document.

For example:

$ curl 127.0.0.1:9001/v2/zones -H 'Content-Type: application/json' --data '
  {
    "name": "example.com.",
    "email": "example@example.com"
  }'

{"status": "PENDING",.....
$ curl 127.0.0.1:9001/v2/zones
{"zones": [{"status": "ACTIVE",.....

The ACTIVE status shows that the zone propagated. So you should be able to perform a DNS query and see it:

$ dig @127.0.0.1 example.com SOA +short
ns1-1.example.org. example.example.com. 1487884120 3531 600 86400 3600

You can find the IP Address of your server by running

ip addr show eth0 | grep "inet\b" | awk '{print $2}' | cut -d/ -f1

If you have Keystone set up, you can use it by configuring the [keystone_authtoken] section and changing the auth_strategy = keystone in the service:api section. This will make it easier to use clients like the openstack CLI that expect Keystone.