From e516ea509940113175cce24382c64d78a2fa42e3 Mon Sep 17 00:00:00 2001
From: Eduardo Gonzalez <dabarren@gmail.com>
Date: Mon, 23 Jan 2017 17:01:02 +0000
Subject: [PATCH] Integrate designate with neutron

Integrate designate service with neutron to allow instances
and floatingip resolve designate dns.
MDNS service need to be reachable from nova instances
in order to resolve DNS queries.
Added new dns_interface to make this configurable.
Add designate guide.

Closes-Bug: #1661330

Change-Id: I5a2ac5cf2a9aa0977ae42d53dd64699623ddf3ed
---
 ansible/group_vars/all.yml                    |   2 +
 ansible/roles/designate/tasks/precheck.yml    |   2 +-
 .../designate/templates/designate.conf.j2     |  20 ++-
 ansible/roles/neutron/defaults/main.yml       |  13 ++
 .../roles/neutron/templates/ml2_conf.ini.j2   |   8 +-
 .../roles/neutron/templates/neutron.conf.j2   |  21 +++
 doc/designate-guide.rst                       | 122 ++++++++++++++++++
 doc/index.rst                                 |   1 +
 etc/kolla/globals.yml                         |   1 +
 9 files changed, 179 insertions(+), 11 deletions(-)
 create mode 100644 doc/designate-guide.rst

diff --git a/ansible/group_vars/all.yml b/ansible/group_vars/all.yml
index 534639bf64..4b76e77b8b 100644
--- a/ansible/group_vars/all.yml
+++ b/ansible/group_vars/all.yml
@@ -118,6 +118,7 @@ storage_interface: "{{ network_interface }}"
 cluster_interface: "{{ network_interface }}"
 tunnel_interface: "{{ network_interface }}"
 bifrost_network_interface: "{{ network_interface }}"
+dns_interface: "{{ network_interface }}"
 tunnel_interface_address: "{{ hostvars[inventory_hostname]['ansible_' + tunnel_interface]['ipv4']['address'] }}"
 
 # Valid options are [ openvswitch, linuxbridge, sfc ]
@@ -359,6 +360,7 @@ enable_watcher: "no"
 ironic_keystone_user: "ironic"
 neutron_keystone_user: "neutron"
 nova_keystone_user: "nova"
+designate_keystone_user: "designate"
 
 # Nova fake driver and the number of fake driver per compute node
 enable_nova_fake: "no"
diff --git a/ansible/roles/designate/tasks/precheck.yml b/ansible/roles/designate/tasks/precheck.yml
index dd8dc1c0f8..546547cb21 100644
--- a/ansible/roles/designate/tasks/precheck.yml
+++ b/ansible/roles/designate/tasks/precheck.yml
@@ -21,7 +21,7 @@
 
 - name: Checking free port for designate mdns
   wait_for:
-    host: "{{ hostvars[inventory_hostname]['ansible_' + api_interface]['ipv4']['address'] }}"
+    host: "{{ hostvars[inventory_hostname]['ansible_' + dns_interface]['ipv4']['address'] }}"
     port: "{{ designate_mdns_port }}"
     connect_timeout: 1
     state: stopped
diff --git a/ansible/roles/designate/templates/designate.conf.j2 b/ansible/roles/designate/templates/designate.conf.j2
index d13f54a7c1..ee0a09d8f7 100644
--- a/ansible/roles/designate/templates/designate.conf.j2
+++ b/ansible/roles/designate/templates/designate.conf.j2
@@ -39,7 +39,7 @@ enabled_notification_handlers = nova_fixed, neutron_floatingip
 workers = {{ openstack_service_workers }}
 
 [service:mdns]
-listen = {{ hostvars[inventory_hostname]['ansible_' + api_interface]['ipv4']['address'] }}:{{ designate_mdns_port }}
+listen = {{ hostvars[inventory_hostname]['ansible_' + dns_interface]['ipv4']['address'] }}:{{ designate_mdns_port }}
 workers = {{ openstack_service_workers }}
 
 [service:worker]
@@ -66,18 +66,30 @@ max_retries = 10
 idle_timeout = 3600
 
 [handler:nova_fixed]
+#NOTE: zone_id must be manually filled an ID from openstack zone list
+zone_id =
 notification_topics = notifications_designate
 control_exchange = nova
-format = '(display_name)s.%(domain)s'
+formatv4 = '%(octet0)s-%(octet1)s-%(octet2)s-%(octet3)s.%(zone)s'
+formatv4 = '%(hostname)s.%(project)s.%(zone)s'
+formatv4 = '%(hostname)s.%(zone)s'
+formatv6 = '%(hostname)s.%(zone)s'
+formatv6 = '%(hostname)s.%(project)s.%(zone)s'
 
 [handler:neutron_floatingip]
+#NOTE: zone_id must be manually filled an ID from openstack zone list
+zone_id =
 notification_topics = notifications_designate
 control_exchange = neutron
-format = '%(octet0)s-%(octet1)s-%(octet2)s-%(octet3)s.%(domain)s'
+formatv4 = '%(octet0)s-%(octet1)s-%(octet2)s-%(octet3)s.%(zone)s'
+formatv4 = '%(hostname)s.%(project)s.%(zone)s'
+formatv4 = '%(hostname)s.%(zone)s'
+formatv6 = '%(hostname)s.%(zone)s'
+formatv6 = '%(hostname)s.%(project)s.%(zone)s'
 
 [oslo_messaging_notifications]
 topics = notifications_designate
-driver = messaging
+driver = messagingv2
 
 [oslo_messaging_rabbit]
 rabbit_userid = {{ rabbitmq_user }}
diff --git a/ansible/roles/neutron/defaults/main.yml b/ansible/roles/neutron/defaults/main.yml
index ad8a3a43e2..2b2636ab7b 100644
--- a/ansible/roles/neutron/defaults/main.yml
+++ b/ansible/roles/neutron/defaults/main.yml
@@ -73,3 +73,16 @@ neutron_logging_debug: "{{ openstack_logging_debug }}"
 neutron_bridge_name: "br-ex"
 
 openstack_neutron_auth: "{{ openstack_auth }}"
+
+####################
+# Extension drivers
+####################
+extension_drivers:
+  - name: "qos"
+    enabled: "{{ enable_neutron_qos | bool }}"
+  - name: "port_security"
+    enabled: "{{ enable_tacker | bool or enable_designate | bool }}"
+  - name: "dns"
+    enabled: "{{ enable_designate | bool }}"
+
+neutron_extension_drivers: "{{ extension_drivers|selectattr('enabled', 'equalto', true)|list }}"
diff --git a/ansible/roles/neutron/templates/ml2_conf.ini.j2 b/ansible/roles/neutron/templates/ml2_conf.ini.j2
index b9cb102af3..c5f976f65d 100644
--- a/ansible/roles/neutron/templates/ml2_conf.ini.j2
+++ b/ansible/roles/neutron/templates/ml2_conf.ini.j2
@@ -15,12 +15,8 @@ mechanism_drivers = openvswitch,l2population
 mechanism_drivers = linuxbridge,l2population
 {% endif %}
 
-{% if enable_neutron_qos | bool %}
-extension_drivers = qos
-{% endif %}
-
-{% if enable_tacker | bool %}
-extension_drivers = port_security
+{% if extension_drivers %}
+extension_drivers = {{ neutron_extension_drivers|map(attribute='name')|join(',') }} 
 {% endif %}
 
 [ml2_type_vlan]
diff --git a/ansible/roles/neutron/templates/neutron.conf.j2 b/ansible/roles/neutron/templates/neutron.conf.j2
index cf1e0214a0..57399ebec3 100644
--- a/ansible/roles/neutron/templates/neutron.conf.j2
+++ b/ansible/roles/neutron/templates/neutron.conf.j2
@@ -50,6 +50,11 @@ transport_url = rabbit://{% for host in groups['rabbitmq'] %}{{ rabbitmq_user }}
 router_distributed = True
 {% endif %}
 
+{% if enable_designate | bool %}
+dns_domain = {{ designate_ns_record }}.
+external_dns_driver = designate
+{% endif %}
+
 [nova]
 auth_url = {{ keystone_admin_url }}
 auth_type = password
@@ -109,3 +114,19 @@ drivers = ovs
 [octavia]
 base_url = {{ internal_protocol }}://{{ kolla_internal_fqdn }}:{{ octavia_api_port }}
 {% endif %}
+
+{% if enable_designate | bool %}
+[designate]
+url = {{ internal_protocol }}://{{ kolla_internal_fqdn }}:{{ designate_api_port }}/v2
+auth_uri = {{ internal_protocol }}://{{ kolla_internal_fqdn }}:{{ keystone_public_port }}
+auth_url = {{ admin_protocol }}://{{ kolla_internal_fqdn }}:{{ keystone_admin_port }}
+auth_type = password
+project_domain_id = default
+user_domain_id = default
+project_name = service
+username = {{ designate_keystone_user }}
+password = {{ designate_keystone_password }}
+allow_reverse_dns_lookup = True
+ipv4_ptr_zone_prefix_size = 24
+ipv6_ptr_zone_prefix_size = 116
+{% endif %}
diff --git a/doc/designate-guide.rst b/doc/designate-guide.rst
new file mode 100644
index 0000000000..9a2e35552c
--- /dev/null
+++ b/doc/designate-guide.rst
@@ -0,0 +1,122 @@
+.. _designate-guide:
+
+==================
+Designate in Kolla
+==================
+
+Overview
+========
+Designate provides DNSaaS services for OpenStack:
+
+  -  REST API for domain/record management
+  -  Multi-tenant
+  -  Integrated with Keystone for authentication
+  -  Framework in place to integrate with Nova and Neutron
+     notifications (for auto-generated records)
+  -  Support for PowerDNS and Bind9 out of the box
+
+Configuration on Kolla deployment
+---------------------------------
+
+Enable Designate service in ``/etc/kolla/globals.yml``
+
+.. code-block:: console
+
+    enable_designate: "yes"
+
+Configure Designate options in ``/etc/kolla/globals.yml``
+
+.. important::
+
+    Designate MDNS node requires the ``dns_interface`` to be reachable from
+    public network.
+
+.. code-block:: console
+
+    dns_interface: "eth1"
+    designate_backend: "bind9"
+    designate_ns_record: "sample.openstack.org"
+
+Neutron and Nova Integration
+----------------------------
+
+Create default Designate Zone for Neutron:
+
+.. code-block:: console
+
+    $ openstack zone create --email admin@sample.openstack.org sample.openstack.org.
+
+Create designate-sink custom configuration folder:
+
+.. code-block:: console
+
+   $ mkdir -p /etc/kolla/config/designate/designate-sink/
+
+Append Designate Zone ID in ``/etc/kolla/config/designate/designate-sink.conf``
+
+.. code-block:: console
+
+    [handler:nova_fixed]
+    zone_id = <ZONE_ID>
+    [handler:neutron_floatingip]
+    zone_id = <ZONE_ID>
+
+Reconfigure Designate:
+
+.. code-block:: console
+
+    $ kolla-ansible reconfigure -i <INVENTORY_FILE> --tags designate
+
+Verify operation
+----------------
+
+List available networks:
+
+.. code-block:: console
+
+    $ neutron net-list
+
+Associate a domain to a network:
+
+.. code-block:: console
+
+    $ neutron net-update <NETWORK_ID> --dns_domain sample.openstack.org.
+
+Start an instance:
+
+.. code-block:: console
+
+    $ openstack server create \
+      --image cirros \
+      --flavor m1.tiny \
+      --key-name mykey \
+      --nic net-id=${NETWORK_ID} \
+      my-vm
+
+Check DNS records in Designate:
+
+.. code-block:: console
+
+    $ designate record-list sample.openstack.org.
+    +--------------------------------------+------+---------------------------------------+---------------------------------------------+
+    | id                                   | type | name                                  | data                                        |
+    +--------------------------------------+------+---------------------------------------+---------------------------------------------+
+    | 5aec6f5b-2121-4a2e-90d7-9e4509f79506 | SOA  | sample.openstack.org.                 | sample.openstack.org.                       |
+    |                                      |      |                                       | admin.sample.openstack.org. 1485266928 3514 |
+    |                                      |      |                                       | 600 86400 3600                              |
+    | 578dc94a-df74-4086-a352-a3b2db9233ae | NS   | sample.openstack.org.                 | sample.openstack.org.                       |
+    | de9ff01e-e9ef-4a0f-88ed-6ec5ecabd315 | A    | 192-168-190-232.sample.openstack.org. | 192.168.190.232                             |
+    | f67645ee-829c-4154-a988-75341050a8d6 | A    | my-vm.None.sample.openstack.org.      | 192.168.190.232                             |
+    | e5623d73-4f9f-4b54-9045-b148e0c3342d | A    | my-vm.sample.openstack.org.           | 192.168.190.232                             |
+    +--------------------------------------+------+---------------------------------------+---------------------------------------------+
+
+Query instance DNS information to Designate ``dns_interface`` IP address:
+
+.. code-block:: console
+
+    $ dig +short -p 5354 @<DNS_INTERFACE_IP> my-vm.sample.openstack.org. A
+    192.168.190.232
+
+For more information about how Designate works, see
+`Designate, a DNSaaS component for OpenStack
+<http://docs.openstack.org/developer/designate>`__.
diff --git a/doc/index.rst b/doc/index.rst
index 59e688fcc0..c9685547cf 100644
--- a/doc/index.rst
+++ b/doc/index.rst
@@ -66,6 +66,7 @@ Kolla Services
    external-ceph-guide
    cinder-guide
    cinder-guide-hnas
+   designate-guide
    ironic-guide
    manila-guide
    manila-hnas-guide
diff --git a/etc/kolla/globals.yml b/etc/kolla/globals.yml
index d4f8820eb3..3cf3c71fb5 100644
--- a/etc/kolla/globals.yml
+++ b/etc/kolla/globals.yml
@@ -77,6 +77,7 @@ kolla_internal_vip_address: "10.10.10.254"
 #storage_interface: "{{ network_interface }}"
 #cluster_interface: "{{ network_interface }}"
 #tunnel_interface: "{{ network_interface }}"
+#dns_interface: "{{ network_interface }}"
 
 # This is the raw interface given to neutron as its external network port. Even
 # though an IP address can exist on this interface, it will be unusable in most