Merge "DynECT: Convert to a Pool Backend"

This commit is contained in:
Jenkins 2015-03-31 18:22:28 +00:00 committed by Gerrit Code Review
commit 626e2fe3ae
8 changed files with 160 additions and 75 deletions

View File

@ -33,6 +33,9 @@ source $TOP_DIR/exerciserc
# Skip if designate is not enabled
is_service_enabled designate || exit 55
# Skip if the DynECT backend is in use
[ "$DESIGNATE_BACKEND_DRIVER" != "dynect" ] || exit 55
# Import designate library
source $TOP_DIR/lib/designate
@ -174,9 +177,10 @@ DOMAIN_NAME="exercise-$(openssl rand -hex 4).com."
# Create the domain
designate domain-create --name $DOMAIN_NAME --email devstack@example.org
((NUMBER_OF_RECORDS+=2))
# should have SOA and NS records
ensure_record_present $DOMAIN_NAME SOA $DESIGNATE_TEST_NSREC
ensure_record_present $DOMAIN_NAME NS $DESIGNATE_TEST_NSREC
ensure_record_present $DOMAIN_NAME SOA $DESIGNATE_DEFAULT_NS_RECORD
ensure_record_present $DOMAIN_NAME NS $DESIGNATE_DEFAULT_NS_RECORD
DOMAIN_ID=$(get_domain_id $DOMAIN_NAME 1)
@ -293,8 +297,8 @@ designate domain-delete $DOMAIN_ID
designate domain-get $DOMAIN_ID || echo "good - domain was removed"
# should not have SOA and NS records
ensure_record_absent $DOMAIN_NAME SOA $DESIGNATE_TEST_NSREC
ensure_record_absent $DOMAIN_NAME NS $DESIGNATE_TEST_NSREC
ensure_record_absent $DOMAIN_NAME SOA $DESIGNATE_DEFAULT_NS_RECORD
ensure_record_absent $DOMAIN_NAME NS $DESIGNATE_DEFAULT_NS_RECORD
set +o xtrace
echo "*********************************************************************"

View File

@ -29,8 +29,8 @@ if is_service_enabled designate; then
echo_summary "Starting Designate"
start_designate
echo_summary "Creating Initial Designate Resources"
create_designate_initial_resources
echo_summary "Creating Pool NS Records"
create_designate_ns_records
fi
if [[ "$1" == "unstack" ]]; then

View File

@ -45,6 +45,7 @@ DESIGNATE_BACKEND_DRIVER=${DESIGNATE_BACKEND_DRIVER:=powerdns}
DESIGNATE_POOL_MANAGER_CACHE_DRIVER=${DESIGNATE_POOL_MANAGER_CACHE_DRIVER:-noop}
DESIGNATE_POOL_ID=${DESIGNATE_POOL_ID:-794ccc2c-d751-44fe-b57f-8894c9f5c842}
DESIGNATE_TARGET_ID=${DESIGNATE_TARGET_ID:-f26e0b32-736f-4f0a-831b-039a415c481e}
DESIGNATE_DEFAULT_NS_RECORD=${DESIGNATE_DEFAULT_NS_RECORD:-ns1.devstack.org.}
# Public IP/Port Settings
DESIGNATE_SERVICE_PROTOCOL=${DESIGNATE_SERVICE_PROTOCOL:-$SERVICE_PROTOCOL}
@ -53,7 +54,6 @@ DESIGNATE_SERVICE_PORT=${DESIGNATE_SERVICE_PORT:-9001}
DESIGNATE_SERVICE_PORT_INT=${DESIGNATE_SERVICE_PORT_INT:-19001}
DESIGNATE_SERVICE_PORT_DNS=${DESIGNATE_SERVICE_PORT_DNS:-53}
DESIGNATE_SERVICE_PORT_MDNS=${DESIGNATE_SERVICE_PORT_MDNS:-5354}
DESIGNATE_TEST_NSREC=${DESIGNATE_TEST_NSREC:-ns1.devstack.org.}
DESIGNATE_ENABLED_EXTENSIONS_V1=${DESIGNATE_ENABLED_EXTENSIONS_V1:-"quotas"}
DESIGNATE_ENABLED_EXTENSIONS_V2=${DESIGNATE_ENABLED_EXTENSIONS_V2:-""}
@ -105,17 +105,20 @@ function configure_designate {
# (Re)create ``designate.conf``
rm -f $DESIGNATE_CONF
# General Configuration
iniset_rpc_backend designate $DESIGNATE_CONF DEFAULT
iniset $DESIGNATE_CONF DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL
iniset $DESIGNATE_CONF DEFAULT verbose True
iniset $DESIGNATE_CONF DEFAULT state_path $DESIGNATE_STATE_PATH
iniset $DESIGNATE_CONF DEFAULT root-helper sudo designate-rootwrap $DESIGNATE_ROOTWRAP_CONF
iniset $DESIGNATE_CONF storage:sqlalchemy connection `database_connection_url designate`
iniset $DESIGNATE_CONF service:api enabled_extensions_v1 $DESIGNATE_ENABLED_EXTENSIONS_V1
iniset $DESIGNATE_CONF service:api enabled_extensions_v2 $DESIGNATE_ENABLED_EXTENSIONS_V2
iniset $DESIGNATE_CONF service:api enabled_extensions_admin $DESIGNATE_ENABLED_EXTENSIONS_ADMIN
# Pool Manager
# Install the policy file for the API server
cp $DESIGNATE_DIR/etc/designate/policy.json $DESIGNATE_CONF_DIR/policy.json
iniset $DESIGNATE_CONF DEFAULT policy_file $DESIGNATE_CONF_DIR/policy.json
# Pool Manager Configuration
iniset $DESIGNATE_CONF service:pool_manager pool_id $DESIGNATE_POOL_ID
iniset $DESIGNATE_CONF service:pool_manager cache_driver $DESIGNATE_POOL_MANAGER_CACHE_DRIVER
@ -127,11 +130,25 @@ function configure_designate {
# Pool Options
iniset $DESIGNATE_CONF pool:$DESIGNATE_POOL_ID targets $DESIGNATE_TARGET_ID
# API Configuration
sudo cp $DESIGNATE_DIR/etc/designate/api-paste.ini $DESIGNATE_APIPASTE_CONF
iniset $DESIGNATE_CONF service:api enabled_extensions_v1 $DESIGNATE_ENABLED_EXTENSIONS_V1
iniset $DESIGNATE_CONF service:api enabled_extensions_v2 $DESIGNATE_ENABLED_EXTENSIONS_V2
iniset $DESIGNATE_CONF service:api enabled_extensions_admin $DESIGNATE_ENABLED_EXTENSIONS_ADMIN
iniset $DESIGNATE_CONF service:api api_host $DESIGNATE_SERVICE_HOST
iniset $DESIGNATE_CONF service:api api_base_uri $DESIGNATE_SERVICE_PROTOCOL://$DESIGNATE_SERVICE_HOST:$DESIGNATE_SERVICE_PORT/
iniset $DESIGNATE_CONF service:api enable_api_v1 True
iniset $DESIGNATE_CONF service:api enable_api_v2 True
iniset $DESIGNATE_CONF service:api enable_api_admin True
# mDNS Configuration
iniset $DESIGNATE_CONF service:mdns host $DESIGNATE_SERVICE_HOST
iniset $DESIGNATE_CONF service:mdns port $DESIGNATE_SERVICE_PORT_MDNS
# Root Wrap
sudo cp $DESIGNATE_DIR/etc/designate/rootwrap.conf.sample $DESIGNATE_ROOTWRAP_CONF
iniset $DESIGNATE_ROOTWRAP_CONF DEFAULT filters_path $DESIGNATE_DIR/etc/designate/rootwrap.d root-helper
sudo cp $DESIGNATE_DIR/etc/designate/api-paste.ini $DESIGNATE_APIPASTE_CONF
# Set up the rootwrap sudoers for designate
local rootwrap_sudoer_cmd="$DESIGNATE_BIN_DIR/designate-rootwrap $DESIGNATE_ROOTWRAP_CONF *"
local tempfile=`mktemp`
@ -140,6 +157,21 @@ function configure_designate {
sudo chown root:root $tempfile
sudo mv $tempfile /etc/sudoers.d/designate-rootwrap
# TLS Proxy Configuration
if is_service_enabled tls-proxy; then
# Set the service port for a proxy to take the original
iniset $DESIGNATE_CONF service:api api_port $DESIGNATE_SERVICE_PORT_INT
else
iniset $DESIGNATE_CONF service:api api_port $DESIGNATE_SERVICE_PORT
fi
# Setup the Keystone Integration
if is_service_enabled key; then
iniset $DESIGNATE_CONF service:api auth_strategy keystone
configure_auth_token_middleware $DESIGNATE_CONF designate $DESIGNATE_AUTH_CACHE_DIR
fi
# Logging Configuration
if [ "$SYSLOG" != "False" ]; then
iniset $DESIGNATE_CONF DEFAULT use_syslog True
fi
@ -149,28 +181,7 @@ function configure_designate {
setup_colorized_logging_designate $DESIGNATE_CONF DEFAULT "tenant" "user"
fi
if is_service_enabled key; then
# Setup the Keystone Integration
iniset $DESIGNATE_CONF service:api auth_strategy keystone
configure_auth_token_middleware $DESIGNATE_CONF designate $DESIGNATE_AUTH_CACHE_DIR
fi
iniset $DESIGNATE_CONF service:api api_host $DESIGNATE_SERVICE_HOST
iniset $DESIGNATE_CONF service:api api_base_uri $DESIGNATE_SERVICE_PROTOCOL://$DESIGNATE_SERVICE_HOST:$DESIGNATE_SERVICE_PORT/
iniset $DESIGNATE_CONF service:api enable_api_v1 True
iniset $DESIGNATE_CONF service:api enable_api_v2 True
iniset $DESIGNATE_CONF service:api enable_api_admin True
if is_service_enabled tls-proxy; then
# Set the service port for a proxy to take the original
iniset $DESIGNATE_CONF service:api api_port $DESIGNATE_SERVICE_PORT_INT
else
iniset $DESIGNATE_CONF service:api api_port $DESIGNATE_SERVICE_PORT
fi
# Install the policy file for the API server
cp $DESIGNATE_DIR/etc/designate/policy.json $DESIGNATE_CONF_DIR/policy.json
iniset $DESIGNATE_CONF DEFAULT policy_file $DESIGNATE_CONF_DIR/policy.json
# Backend Plugin Configuation
configure_designate_backend
}
@ -200,9 +211,14 @@ function create_designate_accounts {
fi
}
function create_designate_initial_resources {
#ADMIN_TENANT_ID=$(keystone tenant-list | grep " admin " | get_field 1)
designate server-create --name $DESIGNATE_TEST_NSREC
# create_designate_ns_records - Create Pool NS Records
function create_designate_ns_records {
# Allow Backends to install their own NS Records rather than the default
if function_exists create_designate_ns_records_backend; then
create_designate_ns_records_backend
else
designate server-create --name $DESIGNATE_DEFAULT_NS_RECORD
fi
}
# init_designate - Initialize etc.
@ -212,6 +228,10 @@ function init_designate {
sudo chown $STACK_USER $DESIGNATE_AUTH_CACHE_DIR
rm -f $DESIGNATE_AUTH_CACHE_DIR/*
# Some Designate Backends require mdns be bound to port 53, make that
# doable.
sudo setcap 'cap_net_bind_service=+ep' $(readlink -f /usr/bin/python)
# (Re)create designate database
recreate_database designate utf8

View File

@ -32,8 +32,19 @@ DESIGNATE_DYNECT_PASSWORD=${DESIGNATE_DYNECT_PASSWORD:-password}
DESIGNATE_DYNECT_CONTACT_NICKNAME=${DESIGNATE_DYNECT_CONTACT_NICKNAME:-}
DESIGNATE_DYNECT_JOB_TIMEOUT=${DESIGNATE_DYNECT_JOB_TIMEOUT:-}
DESIGNATE_DYNECT_TIMEOUT=${DESIGNATE_DYNECT_TIMEOUT:-}
DESIGNATE_DYNECT_MASTERS=${DESIGNATE_DYNECT_MASTERS:-$DESIGNATE_SERVICE_HOST}
DESIGNATE_DYNECT_SLAVES=${DESIGNATE_DYNECT_SLAVES:-204.13.249.65:53, 208.78.68.65:53}
DESIGNATE_DYNECT_MASTERS=${DESIGNATE_DYNECT_MASTERS:-"$DESIGNATE_SERVICE_HOST:$DESIGNATE_SERVICE_PORT_MDNS"}
DESIGNATE_DYNECT_NAMESERVERS=${DESIGNATE_DYNECT_NAMESERVERS:-""}
DESIGNATE_DYNECT_ALSO_NOTIFIES=${DESIGNATE_DYNECT_ALSO_NOTIFIES:-"204.13.249.65:53,208.78.68.65:53"}
# Sanity Checks
# -------------
if [ -z "$DESIGNATE_DYNECT_NAMESERVERS" ]; then
die $LINENO "You must configure DESIGNATE_DYNECT_NAMESERVERS"
fi
if [ "$DESIGNATE_SERVICE_PORT_MDNS" != "53" ]; then
die $LINENO "DynECT requires DESIGNATE_SERVICE_PORT_MDNS is set to '53'"
fi
# Entry Points
# ------------
@ -45,16 +56,30 @@ function install_designate_backend {
# configure_designate_backend - make configuration changes, including those to other services
function configure_designate_backend {
# DynECT Backend Settings
iniset $DESIGNATE_CONF backend:dynect masters "$DESIGNATE_DYNECT_MASTERS"
iniset $DESIGNATE_CONF backend:dynect customer_name "$DESIGNATE_DYNECT_CUSTOMER"
iniset $DESIGNATE_CONF backend:dynect username "$DESIGNATE_DYNECT_USERNAME"
iniset $DESIGNATE_CONF backend:dynect password "$DESIGNATE_DYNECT_PASSWORD"
iniset $DESIGNATE_CONF pool_target:$DESIGNATE_TARGET_ID type dynect
iniset $DESIGNATE_CONF pool_target:$DESIGNATE_TARGET_ID masters $DESIGNATE_DYNECT_MASTERS
iniset $DESIGNATE_CONF pool_target:$DESIGNATE_TARGET_ID options "customer_name: $DESIGNATE_DYNECT_CUSTOMER, username: $DESIGNATE_DYNECT_USERNAME, password: $DESIGNATE_DYNECT_PASSWORD"
if [ ! -z $DESIGNATE_DYNECT_CONTACT_NICKNAME ]; then
iniset $DESIGNATE_CONF backend:dynect contact_nickname "$DESIGNATE_DYNECT_CONTACT_NICKNAME"
fi
# Create a Pool Nameserver for each of the DynECT nameservers
local nameserver_ids=""
IFS=',' read -a nameservers <<< "$DESIGNATE_DYNECT_NAMESERVERS"
for nameserver in "${nameservers[@]}"; do
local nameserver_id=`uuidgen`
iniset $DESIGNATE_CONF pool_nameserver:$nameserver_id host $(dig +short A $nameserver | head -n 1)
iniset $DESIGNATE_CONF pool_nameserver:$nameserver_id port 53
# Append the Nameserver ID to the list
nameserver_ids+=${nameserver_id},
done
# Configure the Pool for the set of nameserver IDs, minus the trailing comma
iniset $DESIGNATE_CONF pool:$DESIGNATE_POOL_ID nameservers "${nameserver_ids:0:-1}"
# Configure the Pool to Notify DynECT's Transfer Agents
iniset $DESIGNATE_CONF pool:$DESIGNATE_POOL_ID also_notifies "$DESIGNATE_DYNECT_ALSO_NOTIFIES"
# Global DynECT Backend Settings
if [ ! -z $DESIGNATE_DYNECT_JOB_TIMEOUT ]; then
iniset $DESIGNATE_CONF backend:dynect job_timeout "$DESIGNATE_DYNECT_JOB_TIMEOUT"
fi
@ -64,6 +89,17 @@ function configure_designate_backend {
fi
}
# create_designate_ns_records - Create Pool NS Records
function create_designate_ns_records_backend {
# Build an array of the DynECT nameservers.
IFS=',' read -a ns_records <<< "$DESIGNATE_DYNECT_NAMESERVERS"
# Create a NS Record for each of the DynECT nameservers
for ns_record in "${ns_records[@]}"; do
designate server-create --name "${ns_record%%.}."
done
}
# init_designate_backend - initialize databases, etc.
function init_designate_backend {
:

View File

@ -85,7 +85,7 @@ SCRIPT
ubuntu.vm.network :private_network, ip: "192.168.27.100"
ubuntu.vm.provision :shell, :privileged => true, :inline => "DEBIAN_FRONTEND=noninteractive apt-get update"
ubuntu.vm.provision :shell, :privileged => true, :inline => "DEBIAN_FRONTEND=noninteractive apt-get install --yes git"
ubuntu.vm.provision :shell, :privileged => true, :inline => "DEBIAN_FRONTEND=noninteractive apt-get install --yes git lvm2"
ubuntu.vm.provision :shell, :privileged => false, :inline => $script
end

View File

@ -35,6 +35,21 @@ ENABLED_SERVICES+=,designate,designate-central,designate-api,designate-pool-mana
# designate.backend section of setup.cfg)
#DESIGNATE_POOL_MANAGER_CACHE_DRIVER=noop
# mDNS Service DNS Port Number
#DESIGNATE_SERVICE_PORT_MDNS=5354
# Designate Backend Config
# ========================
# DynECT Backend
# NOTEs:
# - DynECT requires DESIGNATE_SERVICE_PORT_MDNS is set to "53"
# - DESIGNATE_DYNECT_MASTERS must be a Publicly reachable IP, pointed to mDNS
#DESIGNATE_DYNECT_CUSTOMER=
#DESIGNATE_DYNECT_USERNAME=
#DESIGNATE_DYNECT_PASSWORD=
#DESIGNATE_DYNECT_NAMESERVERS=ns1.p13.dynect.net,ns2.p13.dynect.net,ns3.p13.dynect.net,ns4.p13.dynect.net
#DESIGNATE_DYNECT_MASTERS=
# Other Devstack Config
# =====================
# Optional TLS Proxy

View File

@ -30,6 +30,7 @@ from designate.i18n import _LW
LOG = logging.getLogger(__name__)
CONF = cfg.CONF
CFG_GROUP = 'backend:dynect'
@ -225,7 +226,7 @@ class DynClient(object):
"""
status = response.status
timeout = Timeout(cfg.CONF[CFG_GROUP].job_timeout)
timeout = Timeout(CONF[CFG_GROUP].job_timeout)
try:
while status == 307:
time.sleep(1)
@ -247,13 +248,13 @@ class DynClient(object):
try:
response = self._request(method, url, **kwargs)
except DynClientAuthError as e:
except DynClientAuthError:
if retries > 0:
self.token = None
retries = retries - 1
return self.request(method, url, retries, **kwargs)
else:
raise e
raise
if response.status_code == 307:
response = self.poll_response(response)
@ -309,32 +310,37 @@ class DynECTBackend(base.Backend):
)
opts = [
cfg.StrOpt('customer_name', help="Customer name at DynECT."),
cfg.StrOpt('username', help="Username to auth with DynECT."),
cfg.StrOpt('password', help="Password to auth with DynECT.",
secret=True),
cfg.ListOpt('masters',
help="Master servers from which to transfer from."),
cfg.StrOpt('contact_nickname',
help="Nickname that will receive notifications."),
cfg.StrOpt('tsig_key_name', help="TSIG key name."),
cfg.IntOpt('job_timeout', default=30,
help="Timeout in seconds for pulling a job in DynECT."),
cfg.IntOpt('timeout', help="Timeout in seconds for API Requests.",
default=10),
cfg.BoolOpt('timings', help="Measure requests timings.",
default=False)
default=False),
]
return [(group, opts)]
def __init__(self, target):
super(DynECTBackend, self).__init__(target)
self.customer_name = self.options.get('customer_name')
self.username = self.options.get('username')
self.password = self.options.get('password')
self.contact_nickname = self.options.get('contact_nickname', None)
self.tsig_key_name = self.options.get('tsig_key_name', None)
for m in self.masters:
if m.port != 53:
raise exceptions.ConfigurationError(
"DynECT only supports mDNS instances on port 53")
def get_client(self):
return DynClient(
customer_name=cfg.CONF[CFG_GROUP].customer_name,
user_name=cfg.CONF[CFG_GROUP].username,
password=cfg.CONF[CFG_GROUP].password,
timeout=cfg.CONF[CFG_GROUP].timeout,
timings=cfg.CONF[CFG_GROUP].timings)
customer_name=self.customer_name,
user_name=self.username,
password=self.password,
timeout=CONF[CFG_GROUP].timeout,
timings=CONF[CFG_GROUP].timings)
def create_domain(self, context, domain):
LOG.info(_LI('Creating domain %(d_id)s / %(d_name)s') %
@ -342,26 +348,29 @@ class DynECTBackend(base.Backend):
url = '/Secondary/%s' % domain['name'].rstrip('.')
data = {
'masters': cfg.CONF[CFG_GROUP].masters
'masters': [m.host for m in self.masters]
}
if cfg.CONF[CFG_GROUP].contact_nickname is not None:
data['contact_nickname'] = cfg.CONF[CFG_GROUP].contact_nickname
if self.contact_nickname is not None:
data['contact_nickname'] = self.contact_nickname
if cfg.CONF[CFG_GROUP].tsig_key_name is not None:
data['tsig_key_name'] = cfg.CONF[CFG_GROUP].tsig_key_name
if self.tsig_key_name is not None:
data['tsig_key_name'] = self.tsig_key_name
client = self.get_client()
try:
client.post(url, data=data)
except DynClientError as e:
msg = _LI(
"Domain already exists, updating existing domain instead %s")
LOG.info(msg % domain['name'])
for emsg in e.msgs:
if emsg['ERR_CD'] == 'TARGET_EXISTS':
msg = _LI("Domain already exists, updating existing "
"domain instead %s")
LOG.info(msg % domain['name'])
client.put(url, data=data)
break
else:
raise e
client.put(url, data={'activate': True})
client.logout()

View File

@ -80,6 +80,7 @@ designate.notification.handler =
designate.backend =
bind9 = designate.backend.impl_bind9:Bind9Backend
powerdns = designate.backend.impl_powerdns:PowerDNSBackend
dynect = designate.backend.impl_dynect:DynECTBackend
fake = designate.backend.impl_fake:FakeBackend
designate.backend.agent_backend =