Commit eaf47378 authored by Cédric Le Ninivin's avatar Cédric Le Ninivin Committed by Kazuhiko Shiozaki

powerdns: Introduce PowerDNS software release

powerdns: provide basic instanciation

powerdns: add monitoring, promise and reload

powerdns: add replication

power-dns: replication specific for powerdns

powerdns: fix parameter name

powerdns: provide input json schema for powerdns instance

powerdns: Publish current NS record

powerdns: introduce flexible configuration for countries/ geographical zones

powerdns: fix contry configuration list

powerdns: fix country map list

powerdns: add dynamic slave configuration

powerdns: remove recursor

powerdns: reduce log level
parent 1d6ced80
[buildout]
extends =
../autoconf/buildout.cfg
../automake/buildout.cfg
../bison/buildout.cfg
../flex/buildout.cfg
../gcc/buildout.cfg
../git/buildout.cfg
../boost-lib/buildout.cfg
../libtool/buildout.cfg
../make/buildout.cfg
../mariadb/buildout.cfg
../pkgconfig/buildout.cfg
../ragel/buildout.cfg
../zlib/buildout.cfg
parts =
powerdns
[powerdns]
recipe = slapos.recipe.cmmi
url = http://downloads.powerdns.com/releases/pdns-3.3.1.tar.gz
md5sum = 074e2ff211fd12ecad25b5c1cc190dd4
configure-options =
--prefix=${buildout:parts-directory}/${:_buildout_section_name_}
--with-modules="geo"
--with-dynmodules=""
--without-lua
environment =
PATH=${make:location}/bin:${libtool:location}/bin:${pkgconfig:location}/bin:${bison:location}/bin:${flex:location}/bin:${git:location}/bin:${ragel:location}/bin:%(PATH)s
LDFLAGS = -L${boost-lib:location}/lib -Wl,-rpath=${boost-lib:location}/lib -L${zlib:location}/lib -Wl,-rpath -Wl,${zlib:location}/lib -lz
CPPFLAGS=-I${boost-lib:location}/include
make-target =
install
[buildout]
extends =
../../component/gcc/buildout.cfg
../../component/make/buildout.cfg
parts =
ragel
[ragel]
recipe = slapos.recipe.cmmi
url = http://www.complang.org/ragel/ragel-6.8.tar.gz
md5sum = 1bb39745ac23da449019f9f2cb4b0d01
configure-options =
--prefix=${buildout:parts-directory}/${:_buildout_section_name_}
environment =
PATH=${make:location}/bin:%(PATH)s
make-target =
install
{
"type": "object",
"$schema": "http://json-schema.org/draft-04/schema",
"title": "Input Parameters",
"properties": {
"-dns-type": {
"title": "DNS Software type",
"description": "Software type of DNS nodes",
"default": "single-default",
"type": "string"
},
"-dns-software-release-url": {
"title": "DNS Software Release",
"description": "Url of the software release to be used for the nodes",
"default": "",
"type": "string"
},
"-dns-quantity": {
"title": "DNS Quantity",
"description": "DNS Nodes Quantity",
"default": 1,
"type": "integer"
},
"-dns-i-state": {
"title": "Requested state of node i",
"description": "Requested State of node i of the replication. i must inferior or equal to '-dns-quantity'",
"default": "started",
"type": "string"
},
"-sla-i-sla_parameter": {
"title": "sla_parameter used to request node i",
"description": "Parameter used to provide sla parameter to request dns nodes",
"default": "",
"type": "string"
},
"zone": {
"title": "Zone",
"description": "Zone to be handled by the DNS cluster",
"type": "string",
"default": "domain.com",
"pattern": "^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,6}$"
},
"server-admin": {
"title": "Zone Administrator Email",
"description": "Email of the zone administrator, it is used to generate SOA value",
"type": "string",
"default": "admin@domain.com"
},
"dns-name-template-string": {
"title": "DNS domains template string",
"description": "Template used to generate DNS domain name",
"type": "string",
"default": "ns%s." + zone
}
}
}
{% if slap_software_type in software_type -%}
[jinja2-template-base]
recipe = slapos.recipe.template:jinja2
rendered = ${buildout:directory}/${:filename}
extra-context =
context =
import json_module json
key eggs_directory buildout:eggs-directory
key develop_eggs_directory buildout:develop-eggs-directory
key slap_software_type slap-parameter:slap_software_type
key slave_instance_list slap-parameter:slave_instance_list
${:extra-context}
{% set part_list = [] -%}
{% set single_type_key = 'single-' %}
{% if slap_software_type in ("replicate", "RootSoftwareInstance") %}
{% set dns_type = slapparameter_dict.pop('-dns-type', 'single-default') -%}
{% else -%}
{% set dns_type = "%s%s" % (single_type_key, slap_software_type) -%}
{% endif -%}
{% set dns_quantity = slapparameter_dict.pop('-dns-quantity', '1') | int -%}
{% set slave_list_name = 'extra_slave_instance_list' -%}
{% set dns_list = [] %}
{% set dns_domain_list = [] %}
{% set dns_section_list = [] %}
{% set namebase = 'powerdns' -%}
# XXX Dirty hack, not possible to define default value before
{% set sla_computer_powerdns_1_key = '-sla-1-computer_guid' -%}
{% if not sla_computer_powerdns_1_key in slapparameter_dict -%}
{% do slapparameter_dict.__setitem__(sla_computer_powerdns_1_key, '${slap-connection:computer-id}') -%}
{% endif -%}
## DNS set up
{% set zone = slapparameter_dict.pop('zone', 'domain.com') %}
{% set server_admin = slapparameter_dict.pop('server-admin', 'admin@domain.com') %}
{% set dns_name_template_string = slapparameter_dict.pop('dns-name-template-string', 'ns%s.' + zone) %}
# Here we request individualy each dns.
# The presence of sla parameters is checked and added if found
{% for i in range(1, dns_quantity + 1) -%}
{% set dns_name = 'ns%s' % i -%}
{% set dns_domain = dns_name_template_string % i %}
{% set request_section_title = 'request-%s' % dns_name -%}
{% set sla_key = "-sla-%s-" % i -%}
{% set sla_key_length = sla_key | length %}
{% set sla_parameters = [] %}
{% for key in slapparameter_dict.keys() %}
{% if key.startswith(sla_key) %}
{% do sla_parameters.append(key[sla_key_length:]) %}
{% endif -%}
{% endfor -%}
{% do dns_list.append(dns_name) -%}
{% do dns_domain_list.append(dns_domain) -%}
{% do dns_section_list.append(request_section_title) -%}
{% do part_list.append(request_section_title) -%}
[{{request_section_title}}]
<= replicate
name = {{dns_name}}
{% set state_key = "-dns-%s-state" % i %}
{% if slapparameter_dict.has_key(state_key) %}
state = {{ slapparameter_dict.pop(state_key) }}
{% endif%}
config-zone = {{ zone }}
config-soa = {{ "%s,%s" % (dns_domain, server_admin) }}
{% if sla_parameters %}
sla = {{ ' '.join(sla_parameters) }}
{% for parameter in sla_parameters -%}
sla-{{ parameter }} = {{ slapparameter_dict.pop( sla_key + parameter ) }}
{% endfor -%}
{% endif -%}
{% endfor -%}
{% set ns_record = slapparameter_dict.pop('ns-record', ','.join(dns_domain_list)) %}
[replicate]
<= slap-connection
recipe = slapos.cookbook:requestoptional
{% set dns_software_url_key = "-dns-software-release-url" %}
{% if slapparameter_dict.has_key(dns_software_url_key) %}
software-url = {{ slapparameter_dict.pop(dns_software_url_key) }}
{% else %}
software-url = ${slap-connection:software-release-url}
{% endif %}
software-type = {{dns_type}}
return = private-ipv4 public-ipv4 slave-instance-information-list monitor_url
config = {{ ' '.join(slapparameter_dict.keys()) + ' zone soa server-admin ns-record ' + slave_list_name }}
config-server-admin = {{ server_admin }}
config-ns-record = {{ ns_record }}
{% for parameter, value in slapparameter_dict.iteritems() -%}
config-{{parameter}} = {{ value }}
{% endfor -%}
config-{{ slave_list_name }} = {{ json_module.dumps(slave_instance_list) }}
connection-monitor_url =
[publish-information]
recipe = slapos.cookbook:publish
domain = {{ slapparameter_dict.get('domain') }}
slave-amount = {{ slave_instance_list | length }}
ns-record = {{ ns_record }}
{% for dns in dns_section_list %}
{{ dns }}-monitor-url = {{ '${' + dns + ':connection-monitor_url}' }}
{% endfor -%}
[buildout]
parts =
publish-information
{% for part in part_list -%}
{{ ' %s' % part }}
{% endfor -%}
eggs-directory = {{ eggs_directory }}
develop-eggs-directory = {{ develop_eggs_directory }}
offline = true
[slap_connection]
# Kept for backward compatiblity
computer_id = ${slap-connection:computer-id}
partition_id = ${slap-connection:partition-id}
server_url = ${slap-connection:server-url}
software_release_url = ${slap-connection:software-release-url}
key_file = ${slap-connection:key-file}
cert_file = ${slap-connection:cert-file}
[slap-parameter]
slave_instance_list =
-dns-quantity = 1
-dns-type = single-default
{%- endif %}
\ No newline at end of file
{% if slap_software_type in software_type -%}
{% set part_list = [] %}
# Create all needed directories
[directory]
recipe = slapos.cookbook:mkdirectory
bin = $${buildout:directory}/bin/
etc = $${buildout:directory}/etc/
srv = $${buildout:directory}/srv/
var = $${buildout:directory}/var/
template = $${buildout:directory}/template/
backup = $${:srv}/backup
log = $${:var}/log
run = $${:var}/run
service = $${:etc}/service
etc-run = $${:etc}/run
promise = $${:etc}/promise
logrotate-backup = $${:backup}/logrotate
logrotate-entries = $${:etc}/logrotate.d
cron-entries = $${:etc}/cron.d
crontabs = $${:etc}/crontabs
cronstamps = $${:etc}/cronstamps
ca-dir = $${:srv}/ssl
# Instance parameters
[instance-parameter]
# Fetches parameters defined in SlapOS Master for this instance.
# Always the same.
recipe = slapos.cookbook:slapconfiguration.serialised
computer = $${slap-connection:computer-id}
partition = $${slap-connection:partition-id}
url = $${slap-connection:server-url}
key = $${slap-connection:key-file}
cert = $${slap-connection:cert-file}
# Generic jinja section to extend
[jinja2-template-base]
recipe = slapos.recipe.template:jinja2
rendered = $${buildout:directory}/$${:filename}
extra-context =
context =
import json_module json
key eggs_directory buildout:eggs-directory
key develop_eggs_directory buildout:develop-eggs-directory
key slap_software_type instance-parameter:slap-software-type
key slapparameter_dict instance-parameter:configuration
section directory directory
$${:extra-context}
####################
# PowerDNS sections
#
[pdns]
configuration = $${pdns-directory:configuration}/pdns.conf
local-ipv4 = $${instance-parameter:ipv4-random}
ipv6 = $${instance-parameter:ipv6-random}
port = 5353
socket-directory = $${pdns-directory:socket}
webserver-port = 8088
[geo]
ip-map-zonefile = ${iso-list:location}/${iso-list:filename}
geo-maps = $${pdns-directory:geo-maps}
[pdns-directory]
recipe = slapos.cookbook:mkdirectory
configuration = $${directory:etc}/pdns
geo-maps = $${:configuration}/geo-maps
socket = $${directory:run}/pdns-socket
[pdns-configuration-template]
< = jinja2-template-base
template = ${template-pdns-configuration:target}
rendered = $${pdns:configuration}
extra-context =
section pdns pdns
section geo geo
# Executables
[pdns-server]
recipe = slapos.cookbook:wrapper
command-line = ${powerdns:location}/sbin/pdns_server --config-dir=$${pdns-directory:configuration}
wrapper-path = $${directory:service}/pdns
[pdns-reload]
recipe = slapos.cookbook:wrapper
command-line = ${powerdns:location}/bin/pdns_control reload --config-dir=$${pdns-directory:configuration}
wrapper-path = $${directory:etc-run}/pdns-reload
# Promises
[pdns-promise-listen-port]
recipe = slapos.cookbook:check_port_listening
path = $${directory:promise}/pdns-port-listening
hostname = $${pdns:local-ipv4}
port = $${pdns:port}
#####################
# Power DNS Slave configuration
#
{% set slave_instance_list = json_module.loads(slapparameter_dict.get('extra_slave_instance_list', '')) %}
# Iter through slave list to prepare configuration
{% for slave in slave_instance_list %}
{% if 'record' in slave and 'origin' in slave and 'default' in slave %}
{% set slave_reference = slave.get('slave_reference') %}
{% set slave_section_name = 'map-configuration-%s' % slave_reference %}
{% do part_list.append(slave_section_name) %}
[{{ slave_section_name }}]
< = jinja2-template-base
template = ${template-cdn-conf:location}/${template-cdn-conf:filename}
rendered = $${geo:geo-maps}/{{ slave_reference }}
configuration = {{ json_module.dumps(slave) }}
extra-context =
key json_cdn :configuration
{% endif %}
{% endfor %}
[buildout]
parts =
pdns-configuration-template
pdns-server
pdns-reload
pdns-promise-listen-port
{% for part in part_list %}
{{ ' %s' % part }}
{% endfor %}
## Monitoring part
###Parts to add for monitoring
certificate-authority
cron-entry-monitor
cron-entry-rss
deploy-index
deploy-settings-cgi
deploy-status-cgi
deploy-status-history-cgi
setup-static-files
certificate-authority
zero-parameters
public-symlink
cgi-httpd-wrapper
cgi-httpd-graceful-wrapper
monitor-promise
monitor-instance-log-access
extends = ${monitor-template:output}
eggs-directory = {{ eggs_directory }}
develop-eggs-directory = {{ develop_eggs_directory }}
offline = true
{% endif%}
\ No newline at end of file
[buildout]
parts =
switch-softwaretype
eggs-directory = ${buildout:eggs-directory}
develop-eggs-directory = ${buildout:develop-eggs-directory}
offline = true
[switch-softwaretype]
recipe = slapos.cookbook:softwaretype
default = $${dynamic-powerdns-replicate:rendered}
single-default = $${dynamic-template-powerdns:rendered}
[jinja2-template-base]
recipe = slapos.recipe.template:jinja2
rendered = $${buildout:directory}/$${:filename}
extra-context =
context =
import json_module json
key eggs_directory buildout:eggs-directory
key develop_eggs_directory buildout:develop-eggs-directory
key slap_software_type slap-parameters:slap-software-type
key slapparameter_dict slap-parameters:configuration
key slave_instance_list slap-parameters:slave-instance-list
$${:extra-context}
[dynamic-template-powerdns]
< = jinja2-template-base
template = ${template-powerdns:output}
filename = instance-powerdns.cfg
extensions = jinja2.ext.do
extra-context =
# Must match the key id in [switch-softwaretype] which uses this section.
raw software_type single-default
[dynamic-powerdns-replicate]
< = jinja2-template-base
template = ${template-dns-replicate:target}
filename = instance-apache-replicate.cfg
extensions = jinja2.ext.do
extra-context =
# Must match the key id in [switch-softwaretype] which uses this section.
raw software_type RootSoftwareInstance-default
[slap-parameters]
recipe = slapos.cookbook:slapconfiguration
computer = $${slap-connection:computer-id}
partition = $${slap-connection:partition-id}
url = $${slap-connection:server-url}
key = $${slap-connection:key-file}
cert = $${slap-connection:cert-file}
slave-instance-list =
\ No newline at end of file
{
"type": "object",
"$schema": "http://json-schema.org/draft-04/schema",
"title": "Input Parameters",
"properties": {
"record": {
"title": "Record",
"description": "Record for the configuration",
"type": "string"
},
"origin": {
"title": "Origin",
"description": "Used to qualify RR in the configuration. i.e.: if your origin is a.example.com and the RR for Europe is 'eu' the european clients will use eu.a.exmple.com",
"type": "string"
},
"default": {
"title": "Default RR",
"description": "Defautl record to use when the ip is not regognized",
"type": "string"
},
"europe": {
"title": "Europe RR",
"description": "Records to use for Europe",
"default": "eu",
"type": "string"
},
"africa": {
"title": "Africa RR",
"description": "Records to use for Africa",
"default": "af",
"type": "string"
},
"south-america": {
"title": "South America RR",
"description": "Records to use for South America",
"default": "sa",
"type": "string"
},
"north-america": {
"title": "North America RR",
"description": "Records to use for North America",
"default": "na",
"type": "string"
},
"china": {
"title": "China RR",
"description": "Records to use for China",
"default": "cn",
"type": "string"
},
"japan": {
"title": "Japan RR",
"description": "Records to use for Japan",
"default": "jp",
"type": "string"
},
"hong-kong": {
"title": "Honk Kong RR",
"description": "Records to use for Hong Kong",
"default": "hk",
"type": "string"
},
"east-asia": {
"title": "East Asia RR",
"description": "Records to use for East Asia",
"default": "as",
"type": "string"
},
"west-asia": {
"title": "West Asia RR",
"description": "Records to use for West Asia",
"default": "eu",
"type": "string"
},
"oceania": {
"title": "Oceania RR",
"description": "Records to use for Oceania",
"default": "oc",
"type": "string"
}
}
}
[buildout]
extends =
../../stack/slapos.cfg
../../component/powerdns/buildout.cfg
# Monitoring stack
../../stack/monitor/buildout.cfg
parts =
template
slapos-cookbook
monitor-eggs
eggs
[eggs]
recipe = zc.recipe.egg
eggs =
plone.recipe.command
[template]
recipe = slapos.recipe.template
url = ${:_profile_base_location_}/instance.cfg
#md5sum = 5c22b1e0fe601255ebf19adf6093489f
output = ${buildout:directory}/template.cfg
mode = 0644
[template-powerdns]
recipe = slapos.recipe.template
url = ${:_profile_base_location_}/instance-powerdns.cfg
#md5sum = 05216295ad8ab5ebf34644ac253f0db6
output = ${buildout:directory}/template-powerdns.cfg
mode = 0644
[template-pdns-configuration]
recipe = slapos.recipe.build:download
url = ${:_profile_base_location_}/template/pdns.conf.jinja2
#md5sum = 72922908c1f4e72c92bb03e072660c7c
mode = 640
[template-dns-replicate]
recipe = slapos.recipe.build:download
url = ${:_profile_base_location_}/instance-powerdns-replicate.cfg.jinja2
#md5sum = 5de85259870dc4364954018041561882
mode = 0644
[iso-list]
recipe = hexagonit.recipe.download
url = ${:_profile_base_location_}/template/zz.countries.nexedi.dk.rbldnsd
#md5sum = 950a19be225a25309a3bda3f61fb5f6a
location = ${buildout:parts-directory}/${:_buildout_section_name_}
filename = zz.countries.nexedi.dk.rbldnsd
download-only = true
mode = 0644
[template-cdn-conf]
recipe = hexagonit.recipe.download
url = ${:_profile_base_location_}/template/cdn.conf.in
#md5sum = 950a19be225a25309a3bda3f61fb5f6a
location = ${buildout:parts-directory}/${:_buildout_section_name_}
filename = cdn.conf.in
download-only = true
mode = 0644
This diff is collapsed.
# -------------------------------------------------------------------------
# Configure ip/port binding
local-address={{ pdns.get('local-ipv4') }}
local-ipv6={{ pdns.get('ipv6') }}
local-port={{ pdns.get('port') }}
socket-dir={{ pdns.get('socket-directory') }}
# Monitoring
webserver=yes
webserver-address={{ pdns.get('local-ipv4') }}
webserver-port={{ pdns.get('webserver-port') }}
# These totally disable query+packet caching for all zones. This is necessary
# because otherwise when the exact same question is asked twice in a short
# period of time (by default, 10 seconds), the same response will be given
# without any backends getting involved.
#
# This is bad for geobackend because obviously every question can potentially
# require a new answer based only on the IP of the user's nameserver. Now, it
# should be noted that if you have other zones in PowerDNS then they will have
# their query cache disabled as well. That's not ideal, so you probably want
# to run a separate instance of PowerDNS just for geobackend. Maybe one day
# there will be config options to set per-zone query caching time or something.
query-cache-ttl=0
cache-ttl=0
# Log a lot of stuff. Logging is slow. We will disable this when we are happy
# things are working. :)
log-dns-details=yes
log-dns-queries=yes
log-failed-updates=yes
loglevel=4
# This disables wildcards which is more efficient. geobackend doesn't use
# them, so if none of your backends need them, set this, otherwise comment it
# out.
# wildcards=no
# The geobackend
launch=geo
# The zone that your geo-balanced RR is inside of. The whole zone has to be
# delegated to the PowerDNS backend, so you will generally want to make up some
# subzone of your main zone. We chose "geo.blitzed.org".
#
geo-zone={{ slapparameter_dict.get('zone', 'example.com') }}
# The only parts of the SOA for "geo.blitzed.org" that apply here are the
# master server name and the contact address.
geo-soa-values={{ slapparameter_dict.get('soa', 'ns0.example.com,admin@example.com') }}
# List of NS records of the PowerDNS servers that are authoritative for your
# GLB zone.
geo-ns-records={{ slapparameter_dict.get('ns-record', 'ns0.example.com,ns1.example.com') }}
# The TTL of the CNAME records that geobackend will return. Since the same
# resolver will always get the same CNAME (apart from if the director-map
# changes) it is safe to return a reasonable TTL, so if you leave this
# commented then a sane default will be chosen.
#geo-ttl=3600
# The TTL of the NS records that will be returned. Leave this commented if you
# don't understand.
#geo-ns-ttl=86400
# This is the real guts of the data that drives this backend. This is a DNS
# zone file for RBLDNSD, a nameserver specialised for running large DNS zones
# typical of DNSBLs and such. We choose it for our data because it is easier
# to parse than the BIND-format one.
#
# Anyway, it comes from http://countries.nerd.dk/more.html - there are details
# there for how to rsync your own copy. You'll want to do that regularly,
# every couple of days maybe. We believe the nerd.dk guys take the netblock
# info from Regional Internet Registries (RIRs) like RIPE, ARIN, APNIC. From
# that they build a big zonefile of IP/prefixlen -> ISO-country-code mappings.
geo-ip-map-zonefile={{ geo.get('ip-map-zonefile') }}
# And finally this last directive tells the geobackend where to find the map
# files that say a) which RR to answer for, and b) what actual resource record
# to return for each ISO country code. The setting here is a comma-separated
# list of paths, each of which may either be a single map file or a directory
# that will contain map files. If you are only ever going to serve one RR then
# a single file is probably better, but if you're going to serve many then a
# directory would probably be better. The rest of this documentation will
# assume you chose a directory.
geo-maps={{ geo.get('geo-maps') }}
# -------------------------------------------------------------------------
\ No newline at end of file
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment