Designate - Neutron integration

This patchset implements new relation ("external-dns") using new
interface ("designate") between designate and neutron-api charms.
The following charm options have been added:

* "reverse-dns-lookup"
* "ipv4-ptr-zone-prefix-size"
* "ipv6-ptr-zone-prefix-size"

The patchset contains changes to various items (config files, hooks,
template files and unit tests).

When neutron-api is related to designate, the notification topic
previously used to send notification events to designate will be
disabled (as the DNS driver method is preferred).

Change-Id: I13b2ab39bd1daac13112398762f2be06022594b0
Closes-Bug: #1704769
This commit is contained in:
Tytus Kurek 2017-11-20 10:52:41 +01:00 committed by David Ames
parent 00b52d10b1
commit 95c045d1ce
16 changed files with 199 additions and 9 deletions

View File

@ -91,6 +91,34 @@ list of configured nameservers.
For more information refer to the OpenStack documentation on
[DNS Integration](https://docs.openstack.org/ocata/networking-guide/config-dns-int.html).
# External DNS for Cloud Guests
To add support for DNS record auto-generation when Neutron ports and
floating IPs are created the charm needs a relation with designate charm:
juju deploy designate
juju add-relation neutron-api designate
In order to enable the creation of reverse lookup (PTR) records, enable
"allow-reverse-dns-lookup" charm option:
juju config neutron-api allow-reverse-dns-lookup=True
and configure the following charm options:
juju config neutron-api ipv4-ptr-zone-prefix-size=<IPV4 PREFIX SIZE>
juju config neutron-api ipv6-ptr-zone-prefix-size=<IPV6 PREFIX SIZE>
For example, if prefix sizes of your IPv4 and IPv6 subnets are
"24" (e.g. "192.168.0.0/24") and "64" (e.g. "fdcd:06ca:e498:216b::/64")
respectively, configure the charm options as follows:
juju config neutron-api ipv4-ptr-zone-prefix-size=24
juju config neutron-api ipv6-ptr-zone-prefix-size=64
For more information refer to the OpenStack documentation on
[DNS Integration](https://docs.openstack.org/ocata/networking-guide/config-dns-int.html)
# Network Space support
This charm supports the use of Juju Network Spaces, allowing the charm

View File

@ -692,3 +692,25 @@ options:
Repository from which to install Calico packages. If set, must be
a PPA URL, of the form ppa:somecustom/ppa. Changing this value
after installation will force an immediate software upgrade.
reverse-dns-lookup:
type: boolean
default: False
description: |
A boolean value specifying whether to enable or not the creation of
reverse lookup (PTR) records.
.
NOTE: Use only when relating neutron-api charm to designate charm.
ipv4-ptr-zone-prefix-size:
type: int
default: 24
description: |
The size in bits of the prefix for the IPv4 reverse lookup (PTR) zones.
.
NOTE: Use only when "reverse-dns-lookup" option is set to "True".
ipv6-ptr-zone-prefix-size:
type: int
default: 64
description: |
The size in bits of the prefix for the IPv6 reverse lookup (PTR) zones.
.
NOTE: Use only when "reverse-dns-lookup" option is set to "True".

View File

@ -0,0 +1 @@
neutron_api_hooks.py

View File

@ -0,0 +1 @@
neutron_api_hooks.py

View File

@ -0,0 +1 @@
neutron_api_hooks.py

View File

@ -0,0 +1 @@
neutron_api_hooks.py

View File

@ -400,15 +400,23 @@ class NeutronCCContext(context.NeutronContext):
if vni_ranges:
ctxt['vni_ranges'] = ','.join(vni_ranges.split())
extension_drivers = []
if config('enable-ml2-port-security'):
extension_drivers.append(EXTENSION_DRIVER_PORT_SECURITY)
enable_dns_extension_driver = False
dns_domain = get_dns_domain()
if dns_domain:
extension_drivers.append(EXTENSION_DRIVER_DNS)
enable_dns_extension_driver = True
ctxt['dns_domain'] = dns_domain
if cmp_release >= 'mitaka':
for rid in relation_ids('external-dns'):
if related_units(rid):
enable_dns_extension_driver = True
extension_drivers = []
if config('enable-ml2-port-security'):
extension_drivers.append(EXTENSION_DRIVER_PORT_SECURITY)
if enable_dns_extension_driver:
extension_drivers.append(EXTENSION_DRIVER_DNS)
if is_qos_requested_and_valid():
extension_drivers.append(EXTENSION_DRIVER_QOS)
@ -707,3 +715,25 @@ class NeutronAMQPContext(context.AMQPContext):
context = super(NeutronAMQPContext, self).__call__()
context['notification_topics'] = ','.join(NOTIFICATION_TOPICS)
return context
class DesignateContext(context.OSContextGenerator):
interfaces = ['external-dns']
def __call__(self):
ctxt = {}
for rid in relation_ids('external-dns'):
if related_units(rid):
for unit in related_units(rid):
rdata = relation_get(rid=rid, unit=unit)
ctxt['designate_endpoint'] = rdata.get('endpoint')
if ctxt.get('designate_endpoint') is not None:
ctxt['enable_designate'] = True
allow_reverse_dns_lookup = config('reverse-dns-lookup')
ctxt['allow_reverse_dns_lookup'] = allow_reverse_dns_lookup
if allow_reverse_dns_lookup:
ctxt['ipv4_ptr_zone_prefix_size'] = (
config('ipv4-ptr-zone-prefix-size'))
ctxt['ipv6_ptr_zone_prefix_size'] = (
config('ipv6-ptr-zone-prefix-size'))
return ctxt

View File

@ -713,6 +713,15 @@ def midonet_changed():
CONFIGS.write_all()
@hooks.hook('external-dns-relation-joined',
'external-dns-relation-changed',
'external-dns-relation-departed',
'external-dns-relation-broken')
@restart_on_change(restart_map())
def designate_changed():
CONFIGS.write_all()
@hooks.hook('update-status')
@harden()
@harden()

View File

@ -194,7 +194,8 @@ BASE_RESOURCE_MAP = OrderedDict([
context.BindHostContext(),
context.WorkerConfigContext(),
context.InternalEndpointContext('neutron-common'),
context.MemcacheContext()],
context.MemcacheContext(),
neutron_api_context.DesignateContext()],
}),
(NEUTRON_DEFAULT, {
'services': ['neutron-server'],

View File

@ -55,6 +55,8 @@ requires:
interface: etcd-proxy
midonet:
interface: midonet
external-dns:
interface: designate
peers:
cluster:
interface: neutron-api-ha

View File

@ -69,6 +69,10 @@ notify_nova_on_port_data_changes = True
global_physnet_mtu = {{ global_physnet_mtu }}
{% endif -%}
{% if enable_designate -%}
external_dns_driver = designate
{% endif -%}
{% include "section-zeromq" %}
[quotas]
@ -109,3 +113,7 @@ root_helper = sudo /usr/bin/neutron-rootwrap /etc/neutron/rootwrap.conf
lock_path = $state_path/lock
{% include "parts/section-nova" %}
{% if enable_designate -%}
{% include "parts/section-designate" %}
{% endif -%}

View File

@ -69,6 +69,10 @@ notify_nova_on_port_data_changes = True
global_physnet_mtu = {{ global_physnet_mtu }}
{% endif -%}
{% if enable_designate -%}
external_dns_driver = designate
{% endif -%}
{% include "section-zeromq" %}
[quotas]
@ -110,6 +114,10 @@ lock_path = $state_path/lock
{% include "parts/section-nova" %}
{% if enable_designate -%}
{% include "parts/section-designate" %}
{% endif -%}
[service_providers]
service_provider = LOADBALANCERV2:Haproxy:neutron_lbaas.drivers.haproxy.plugin_driver.HaproxyOnHostPluginDriver:default
service_provider = VPN:strongswan:neutron_vpnaas.services.vpn.service_drivers.ipsec.IPsecVPNDriver:default

View File

@ -0,0 +1,11 @@
[designate]
url = {{ designate_endpoint }}/v2
admin_auth_url = {{ auth_protocol }}://{{ auth_host }}:{{ auth_port }}
admin_username = {{ admin_user }}
admin_password = {{ admin_password }}
admin_tenant_name = {{ admin_tenant_name }}
allow_reverse_dns_lookup = {{ allow_reverse_dns_lookup }}
{% if allow_reverse_dns_lookup -%}
ipv4_ptr_zone_prefix_size = {{ ipv4_ptr_zone_prefix_size }}
ipv6_ptr_zone_prefix_size = {{ ipv6_ptr_zone_prefix_size }}
{% endif -%}

View File

@ -69,6 +69,10 @@ notify_nova_on_port_data_changes = True
global_physnet_mtu = {{ global_physnet_mtu }}
{% endif -%}
{% if enable_designate -%}
external_dns_driver = designate
{% endif -%}
{% include "section-zeromq" %}
[quotas]
@ -110,5 +114,9 @@ lock_path = $state_path/lock
{% include "parts/section-nova" %}
{% if enable_designate -%}
{% include "parts/section-designate" %}
{% endif -%}
[service_providers]
service_provider = LOADBALANCERV2:Haproxy:neutron_lbaas.drivers.haproxy.plugin_driver.HaproxyOnHostPluginDriver:default

View File

@ -1114,3 +1114,50 @@ class MidonetContextTest(CharmTestCase):
'midonet_api_port': '8080'}
self.assertEqual(expect, ctxt)
class DesignateContextTest(CharmTestCase):
def setUp(self):
super(DesignateContextTest, self).setUp(context, TO_PATCH)
self.relation_get.side_effect = self.test_relation.get
def tearDown(self):
super(DesignateContextTest, self).tearDown()
def test_designate_no_related_units(self):
self.related_units.return_value = []
ctxt = context.DesignateContext()()
expect = {}
self.assertEquals(expect, ctxt)
def test_designate_related_units_no_reverse_dns_lookup(self):
self.config.side_effect = self.test_config.get
self.related_units.return_value = ['unit1']
self.relation_ids.return_value = ['rid1']
self.test_relation.set({'endpoint': 'http://1.1.1.1:9001'})
self.test_config.set('reverse-dns-lookup', False)
ctxt = context.DesignateContext()()
expect = {'enable_designate': True,
'designate_endpoint': 'http://1.1.1.1:9001',
'allow_reverse_dns_lookup': False}
self.assertEquals(expect, ctxt)
def test_designate_related_units_and_reverse_dns_lookup(self):
self.config.side_effect = self.test_config.get
self.related_units.return_value = ['unit1']
self.relation_ids.return_value = ['rid1']
self.test_relation.set({'endpoint': 'http://1.1.1.1:9001'})
self.test_config.set('reverse-dns-lookup', True)
self.test_config.set('ipv4-ptr-zone-prefix-size', 24)
self.test_config.set('ipv6-ptr-zone-prefix-size', 64)
ctxt = context.DesignateContext()()
expect = {'enable_designate': True,
'designate_endpoint': 'http://1.1.1.1:9001',
'allow_reverse_dns_lookup': True,
'ipv4_ptr_zone_prefix_size': 24,
'ipv6_ptr_zone_prefix_size': 64}
self.assertEquals(expect, ctxt)

View File

@ -1004,3 +1004,15 @@ class NeutronAPIHooksTests(CharmTestCase):
self.assertTrue(self.CONFIGS.register.called)
self.CONFIGS.write.assert_any_call('/etc/init/etcd.conf')
self.CONFIGS.write.assert_any_call('/etc/default/etcd')
def test_designate_peer_joined(self):
self.test_relation.set({
'endpoint': 'http://1.2.3.4:9001',
})
self.relation_ids.side_effect = self._fake_relids
self._call_hook('external-dns-relation-joined')
self.assertTrue(self.CONFIGS.write.called_with(NEUTRON_CONF))
def test_designate_peer_departed(self):
self._call_hook('external-dns-relation-departed')
self.assertTrue(self.CONFIGS.write.called_with(NEUTRON_CONF))