Pools Config Changes
Implement the beginning of a structured pattern for Plugin's to provide configuration into Designate. The chosen pattern has been built to support both config generation, and the ability to define "extra" config options which are based on other config options (i.e. the dynamic sections for each pool server). Change-Id: I1889ac1de3dc90b95533bea3f456ea2bf8e9b845
This commit is contained in:
parent
490118d9ce
commit
504a2607a8
|
@ -38,40 +38,6 @@ if is_fedora; then
|
|||
BIND_GROUP=named
|
||||
fi
|
||||
|
||||
# Local functions
|
||||
#----------------
|
||||
# Set an option in an INI file
|
||||
# wildcard_iniset config-file section option value
|
||||
#
|
||||
# This function is needed to handle sections that have a wildcard in them.
|
||||
function wildcard_iniset {
|
||||
local xtrace=$(set +o | grep xtrace)
|
||||
set +o xtrace
|
||||
local file=$1
|
||||
local section=$2
|
||||
local option=$3
|
||||
local value=$4
|
||||
|
||||
[[ -z $section || -z $option ]] && return
|
||||
|
||||
if ! grep -q "^\[$section\]" "$file" 2>/dev/null; then
|
||||
eval wildcardless_section=$section
|
||||
# Add section at the end
|
||||
echo -e "\n[$wildcardless_section]" >>"$file"
|
||||
fi
|
||||
if ! ini_has_option "$file" "$section" "$option"; then
|
||||
# Add it
|
||||
sed -i -e "/^\[$section\]/ a\\
|
||||
$option = $value
|
||||
" "$file"
|
||||
else
|
||||
local sep=$(echo -ne "\x01")
|
||||
# Replace it
|
||||
sed -i -e '/^\['${section}'\]/,/^\[.*\]/ s'${sep}'^\('${option}'[ \t]*=[ \t]*\).*$'${sep}'\1'"${value}"${sep} "$file"
|
||||
fi
|
||||
$xtrace
|
||||
}
|
||||
|
||||
# Entry Points
|
||||
# ------------
|
||||
|
||||
|
@ -109,11 +75,15 @@ EOF
|
|||
|
||||
# configure_designate_backend - make configuration changes, including those to other services
|
||||
function configure_designate_backend {
|
||||
wildcard_iniset $DESIGNATE_CONF backend:bind9_pool:\\\* masters $DESIGNATE_SERVICE_HOST:$DESIGNATE_SERVICE_PORT_MDNS
|
||||
wildcard_iniset $DESIGNATE_CONF backend:bind9_pool:\\\* rndc_port $DESIGNATE_SERVICE_PORT_RNDC
|
||||
wildcard_iniset $DESIGNATE_CONF backend:bind9_pool:\\\* rndc_host $DESIGNATE_SERVICE_HOST
|
||||
wildcard_iniset $DESIGNATE_CONF backend:bind9_pool:\\\* rndc_config_file "$BIND_CFG_DIR/rndc.conf"
|
||||
wildcard_iniset $DESIGNATE_CONF backend:bind9_pool:\\\* rndc_key_file "$BIND_CFG_DIR/rndc.key"
|
||||
iniset $DESIGNATE_CONF service:pool_manager backends bind9_pool
|
||||
iniset $DESIGNATE_CONF service:mdns slave_nameserver_ips_and_ports "$DESIGNATE_SERVICE_HOST:$DESIGNATE_SERVICE_PORT_DNS"
|
||||
|
||||
iniset $DESIGNATE_CONF backend:bind9_pool masters $DESIGNATE_SERVICE_HOST:$DESIGNATE_SERVICE_PORT_MDNS
|
||||
iniset $DESIGNATE_CONF backend:bind9_pool server_ids $DESIGNATE_SERVER_ID
|
||||
iniset $DESIGNATE_CONF backend:bind9_pool rndc_port $DESIGNATE_SERVICE_PORT_RNDC
|
||||
iniset $DESIGNATE_CONF backend:bind9_pool rndc_host $DESIGNATE_SERVICE_HOST
|
||||
iniset $DESIGNATE_CONF backend:bind9_pool rndc_config_file "$BIND_CFG_DIR/rndc.conf"
|
||||
iniset $DESIGNATE_CONF backend:bind9_pool rndc_key_file "$BIND_CFG_DIR/rndc.key"
|
||||
|
||||
iniset $DESIGNATE_CONF backend:bind9_pool:$DESIGNATE_SERVER_ID host $DESIGNATE_SERVICE_HOST
|
||||
iniset $DESIGNATE_CONF backend:bind9_pool:$DESIGNATE_SERVER_ID port $DESIGNATE_SERVICE_PORT_DNS
|
||||
|
|
|
@ -14,10 +14,10 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
import abc
|
||||
import copy
|
||||
|
||||
from oslo.config import cfg
|
||||
|
||||
import designate.pool_manager.backend_section_name as backend_section_name
|
||||
from designate.openstack.common import log as logging
|
||||
from designate.i18n import _LW
|
||||
from designate import exceptions
|
||||
|
@ -162,6 +162,69 @@ class Backend(DriverPlugin):
|
|||
|
||||
|
||||
class PoolBackend(Backend):
|
||||
@classmethod
|
||||
def get_cfg_opts(cls):
|
||||
group = cfg.OptGroup(
|
||||
name=cls.get_canonical_name(),
|
||||
title='Backend options for %s Backend' % cls.get_plugin_name()
|
||||
)
|
||||
|
||||
opts = [
|
||||
cfg.ListOpt('server_ids', default=[]),
|
||||
cfg.ListOpt('masters', default=['127.0.0.1:5354'],
|
||||
help='Comma-separated list of master DNS servers, in '
|
||||
'<ip-address>:<port> format. If <port> is '
|
||||
'omitted, the default 5354 is used. These are '
|
||||
'mdns servers.'),
|
||||
]
|
||||
|
||||
opts.extend(cls._get_common_cfg_opts())
|
||||
opts.extend(cls._get_global_cfg_opts())
|
||||
|
||||
return [(group, opts)]
|
||||
|
||||
@classmethod
|
||||
def get_extra_cfg_opts(cls):
|
||||
# Common options fot all backends
|
||||
opts = [
|
||||
cfg.ListOpt('masters'),
|
||||
cfg.StrOpt('host', default='127.0.0.1', help='Server Host'),
|
||||
cfg.IntOpt('port', default=53, help='Server Port'),
|
||||
cfg.StrOpt('tsig-key', help='Server TSIG Key'),
|
||||
]
|
||||
|
||||
# Backend specific common options
|
||||
common_cfg_opts = copy.deepcopy(cls._get_common_cfg_opts())
|
||||
|
||||
# Ensure the default value for all common options is reset to None
|
||||
for opt in common_cfg_opts:
|
||||
opt.default = None
|
||||
|
||||
opts.extend(common_cfg_opts)
|
||||
|
||||
# Add any server only config options
|
||||
opts.extend(cls._get_server_cfg_opts())
|
||||
|
||||
result = []
|
||||
global_group = cls.get_canonical_name()
|
||||
|
||||
for server_id in cfg.CONF[global_group].server_ids:
|
||||
group = cfg.OptGroup(name='%s:%s' % (global_group, server_id))
|
||||
result.append((group, opts))
|
||||
|
||||
return result
|
||||
|
||||
@classmethod
|
||||
def _get_common_cfg_opts(cls):
|
||||
return []
|
||||
|
||||
@classmethod
|
||||
def _get_global_cfg_opts(cls):
|
||||
return []
|
||||
|
||||
@classmethod
|
||||
def _get_server_cfg_opts(cls):
|
||||
return []
|
||||
|
||||
def __init__(self, backend_options):
|
||||
super(PoolBackend, self).__init__(None)
|
||||
|
@ -203,60 +266,28 @@ class PoolBackend(Backend):
|
|||
Create the backend_option object. If a server specific backend option
|
||||
value exists, use it. Otherwise use the global backend option value.
|
||||
"""
|
||||
value = cfg.CONF[server_section_name].get(key)
|
||||
value = None
|
||||
try:
|
||||
value = cfg.CONF[server_section_name].get(key)
|
||||
except cfg.NoSuchOptError:
|
||||
pass
|
||||
|
||||
if value is None:
|
||||
value = cfg.CONF[global_section_name].get(key)
|
||||
|
||||
backend_option_values = {
|
||||
'key': key,
|
||||
'value': value
|
||||
}
|
||||
return objects.BackendOption(**backend_option_values)
|
||||
|
||||
@classmethod
|
||||
def _register_opts(cls, backend, server_id):
|
||||
"""
|
||||
Register the global and server specific backend options.
|
||||
"""
|
||||
global_section_name = backend_section_name \
|
||||
.generate_global_section_name(backend)
|
||||
server_section_name = backend_section_name \
|
||||
.generate_server_section_name(backend, server_id)
|
||||
|
||||
# Register the global backend options.
|
||||
global_opts = cls.get_cfg_opts()
|
||||
cfg.CONF.register_group(cfg.OptGroup(name=global_section_name))
|
||||
cfg.CONF.register_opts(global_opts, group=global_section_name)
|
||||
|
||||
# Register the server specific backend options.
|
||||
server_opts = global_opts
|
||||
server_opts.append(cfg.StrOpt('host', default='127.0.0.1',
|
||||
help='Server Host'))
|
||||
server_opts.append(cfg.IntOpt('port', default=53, help='Server Port'))
|
||||
server_opts.append(cfg.StrOpt('tsig-key', help='Server TSIG Key'))
|
||||
cfg.CONF.register_group(cfg.OptGroup(name=server_section_name))
|
||||
cfg.CONF.register_opts(server_opts, group=server_section_name)
|
||||
|
||||
# Ensure the server specific backend options do not have a default
|
||||
# value. This is necessary so the default value does not override
|
||||
# a global backend option value set in the configuration file.
|
||||
for key in cfg.CONF[global_section_name].keys():
|
||||
cfg.CONF.set_default(key, None, group=server_section_name)
|
||||
|
||||
return global_section_name, server_section_name
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_cfg_opts(self):
|
||||
"""
|
||||
Get the configuration options.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def get_server_object(cls, backend, server_id):
|
||||
"""
|
||||
Get the server object from the backend driver for the server_id.
|
||||
"""
|
||||
global_section_name, server_section_name = cls._register_opts(
|
||||
backend, server_id)
|
||||
global_section_name = 'backend:%s' % (backend,)
|
||||
server_section_name = 'backend:%s:%s' % (backend, server_id)
|
||||
|
||||
backend_options = cls._create_backend_option_objects(
|
||||
global_section_name, server_section_name)
|
||||
|
|
|
@ -29,24 +29,28 @@ from designate.backend import base
|
|||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
cfg.CONF.register_group(cfg.OptGroup(
|
||||
name='backend:bind9', title="Configuration for BIND9 Backend"
|
||||
))
|
||||
|
||||
cfg.CONF.register_opts([
|
||||
cfg.StrOpt('rndc-host', default='127.0.0.1', help='RNDC Host'),
|
||||
cfg.IntOpt('rndc-port', default=953, help='RNDC Port'),
|
||||
cfg.StrOpt('rndc-config-file', default=None,
|
||||
help='RNDC Config File'),
|
||||
cfg.StrOpt('rndc-key-file', default=None, help='RNDC Key File'),
|
||||
cfg.StrOpt('nzf-path', default='/var/cache/bind',
|
||||
help='Path where Bind9 stores the nzf files'),
|
||||
], group='backend:bind9')
|
||||
|
||||
|
||||
class Bind9Backend(base.Backend):
|
||||
__plugin_name__ = 'bind9'
|
||||
|
||||
@classmethod
|
||||
def get_cfg_opts(cls):
|
||||
group = cfg.OptGroup(
|
||||
name='backend:bind9', title="Configuration for BIND9 Backend"
|
||||
)
|
||||
|
||||
opts = [
|
||||
cfg.StrOpt('rndc-host', default='127.0.0.1', help='RNDC Host'),
|
||||
cfg.IntOpt('rndc-port', default=953, help='RNDC Port'),
|
||||
cfg.StrOpt('rndc-config-file', default=None,
|
||||
help='RNDC Config File'),
|
||||
cfg.StrOpt('rndc-key-file', default=None, help='RNDC Key File'),
|
||||
cfg.StrOpt('nzf-path', default='/var/cache/bind',
|
||||
help='Path where Bind9 stores the nzf files'),
|
||||
]
|
||||
|
||||
return [(group, opts)]
|
||||
|
||||
def start(self):
|
||||
super(Bind9Backend, self).start()
|
||||
|
||||
|
|
|
@ -24,23 +24,22 @@ from designate.backend import base
|
|||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
cfg_opts = [
|
||||
cfg.ListOpt('masters', default=['127.0.0.1:5354'],
|
||||
help='Comma-separated list of master DNS servers, in '
|
||||
' <ip-address>:<port> format. If <port> is omitted, '
|
||||
'the default 5354 is used. These are mdns servers.'),
|
||||
cfg.StrOpt('rndc-host', default='127.0.0.1', help='RNDC Host'),
|
||||
cfg.IntOpt('rndc-port', default=953, help='RNDC Port'),
|
||||
cfg.StrOpt('rndc-config-file', default=None, help='RNDC Config File'),
|
||||
cfg.StrOpt('rndc-key-file', default=None, help='RNDC Key File'),
|
||||
]
|
||||
DEFAULT_PORT = 5354
|
||||
|
||||
|
||||
class Bind9PoolBackend(base.PoolBackend):
|
||||
__plugin_name__ = 'bind9_pool'
|
||||
|
||||
@classmethod
|
||||
def _get_common_cfg_opts(cls):
|
||||
return [
|
||||
cfg.StrOpt('rndc-host', default='127.0.0.1', help='RNDC Host'),
|
||||
cfg.IntOpt('rndc-port', default=953, help='RNDC Port'),
|
||||
cfg.StrOpt('rndc-config-file', default=None,
|
||||
help='RNDC Config File'),
|
||||
cfg.StrOpt('rndc-key-file', default=None, help='RNDC Key File'),
|
||||
]
|
||||
|
||||
def __init__(self, backend_options):
|
||||
super(Bind9PoolBackend, self).__init__(backend_options)
|
||||
self.masters = [self._parse_master(master)
|
||||
|
@ -73,10 +72,6 @@ class Bind9PoolBackend(base.PoolBackend):
|
|||
'Invalid IP address "%s" in masters option.' % ip_address)
|
||||
return {'ip-address': ip_address, 'port': port}
|
||||
|
||||
@classmethod
|
||||
def get_cfg_opts(cls):
|
||||
return cfg_opts
|
||||
|
||||
def create_domain(self, context, domain):
|
||||
LOG.debug('Create Domain')
|
||||
masters = []
|
||||
|
|
|
@ -30,29 +30,7 @@ from designate.i18n import _LW
|
|||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
GROUP = 'backend:dynect'
|
||||
|
||||
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)
|
||||
]
|
||||
|
||||
cfg.CONF.register_group(
|
||||
cfg.OptGroup(name=GROUP, title='Backend options for DynECT'))
|
||||
|
||||
cfg.CONF.register_opts(OPTS, group=GROUP)
|
||||
CFG_GROUP = 'backend:dynect'
|
||||
|
||||
|
||||
class DynClientError(exceptions.Backend):
|
||||
|
@ -247,7 +225,7 @@ class DynClient(object):
|
|||
"""
|
||||
status = response.status
|
||||
|
||||
timeout = Timeout(cfg.CONF[GROUP].job_timeout)
|
||||
timeout = Timeout(cfg.CONF[CFG_GROUP].job_timeout)
|
||||
try:
|
||||
while status == 307:
|
||||
time.sleep(1)
|
||||
|
@ -324,13 +302,39 @@ class DynECTBackend(base.Backend):
|
|||
"""
|
||||
__plugin_name__ = 'dynect'
|
||||
|
||||
@classmethod
|
||||
def get_cfg_opts(cls):
|
||||
group = cfg.OptGroup(
|
||||
name=CFG_GROUP, title='Backend options for DynECT'
|
||||
)
|
||||
|
||||
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)
|
||||
]
|
||||
|
||||
return [(group, opts)]
|
||||
|
||||
def get_client(self):
|
||||
return DynClient(
|
||||
customer_name=cfg.CONF[GROUP].customer_name,
|
||||
user_name=cfg.CONF[GROUP].username,
|
||||
password=cfg.CONF[GROUP].password,
|
||||
timeout=cfg.CONF[GROUP].timeout,
|
||||
timings=cfg.CONF[GROUP].timings)
|
||||
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)
|
||||
|
||||
def create_domain(self, context, domain):
|
||||
LOG.info(_LI('Creating domain %(d_id)s / %(d_name)s') %
|
||||
|
@ -338,14 +342,14 @@ class DynECTBackend(base.Backend):
|
|||
|
||||
url = '/Secondary/%s' % domain['name'].rstrip('.')
|
||||
data = {
|
||||
'masters': cfg.CONF[GROUP].masters
|
||||
'masters': cfg.CONF[CFG_GROUP].masters
|
||||
}
|
||||
|
||||
if cfg.CONF[GROUP].contact_nickname is not None:
|
||||
data['contact_nickname'] = cfg.CONF[GROUP].contact_nickname
|
||||
if cfg.CONF[CFG_GROUP].contact_nickname is not None:
|
||||
data['contact_nickname'] = cfg.CONF[CFG_GROUP].contact_nickname
|
||||
|
||||
if cfg.CONF[GROUP].tsig_key_name is not None:
|
||||
data['tsig_key_name'] = cfg.CONF[GROUP].tsig_key_name
|
||||
if cfg.CONF[CFG_GROUP].tsig_key_name is not None:
|
||||
data['tsig_key_name'] = cfg.CONF[CFG_GROUP].tsig_key_name
|
||||
|
||||
client = self.get_client()
|
||||
|
||||
|
|
|
@ -29,44 +29,8 @@ from designate.i18n import _LE
|
|||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
cfg.CONF.register_group(cfg.OptGroup(
|
||||
name='backend:ipa', title="Configuration for IPA Backend"
|
||||
))
|
||||
|
||||
IPA_DEFAULT_PORT = 443
|
||||
|
||||
OPTS = [
|
||||
cfg.StrOpt('ipa-host', default='localhost.localdomain',
|
||||
help='IPA RPC listener host - must be FQDN'),
|
||||
cfg.IntOpt('ipa-port', default=IPA_DEFAULT_PORT,
|
||||
help='IPA RPC listener port'),
|
||||
cfg.StrOpt('ipa-client-keytab', default=None,
|
||||
help='Kerberos client keytab file'),
|
||||
cfg.StrOpt('ipa-auth-driver-class',
|
||||
default='designate.backend.impl_ipa.auth.IPAAuth',
|
||||
help='Class that implements the authentication '
|
||||
'driver for IPA'),
|
||||
cfg.StrOpt('ipa-ca-cert', default=None,
|
||||
help='CA certificate for use with https to IPA'),
|
||||
cfg.StrOpt('ipa-base-url', default='/ipa',
|
||||
help='Base URL for IPA RPC, relative to host[:port]'),
|
||||
cfg.StrOpt('ipa-json-url',
|
||||
default='/json',
|
||||
help='URL for IPA JSON RPC, relative to IPA base URL'),
|
||||
cfg.IntOpt('ipa-connect-retries', default=1,
|
||||
help='How many times Designate will attempt to retry '
|
||||
'the connection to IPA before giving up'),
|
||||
cfg.BoolOpt('ipa-force-ns-use', default=False,
|
||||
help='IPA requires that a specified '
|
||||
'name server or SOA MNAME is resolvable - if this '
|
||||
'option is set, Designate will force IPA to use a '
|
||||
'given name server even if it is not resolvable'),
|
||||
cfg.StrOpt('ipa-version', default='2.65',
|
||||
help='IPA RPC JSON version')
|
||||
]
|
||||
|
||||
cfg.CONF.register_opts(OPTS, group='backend:ipa')
|
||||
|
||||
|
||||
class IPABaseError(exceptions.Backend):
|
||||
error_code = 500
|
||||
|
@ -182,6 +146,44 @@ def abs2rel_name(domain, rsetname):
|
|||
class IPABackend(base.Backend):
|
||||
__plugin_name__ = 'ipa'
|
||||
|
||||
@classmethod
|
||||
def get_cfg_opts(cls):
|
||||
group = cfg.OptGroup(
|
||||
name='backend:ipa', title="Configuration for IPA Backend"
|
||||
)
|
||||
|
||||
opts = [
|
||||
cfg.StrOpt('ipa-host', default='localhost.localdomain',
|
||||
help='IPA RPC listener host - must be FQDN'),
|
||||
cfg.IntOpt('ipa-port', default=IPA_DEFAULT_PORT,
|
||||
help='IPA RPC listener port'),
|
||||
cfg.StrOpt('ipa-client-keytab', default=None,
|
||||
help='Kerberos client keytab file'),
|
||||
cfg.StrOpt('ipa-auth-driver-class',
|
||||
default='designate.backend.impl_ipa.auth.IPAAuth',
|
||||
help='Class that implements the authentication '
|
||||
'driver for IPA'),
|
||||
cfg.StrOpt('ipa-ca-cert', default=None,
|
||||
help='CA certificate for use with https to IPA'),
|
||||
cfg.StrOpt('ipa-base-url', default='/ipa',
|
||||
help='Base URL for IPA RPC, relative to host[:port]'),
|
||||
cfg.StrOpt('ipa-json-url',
|
||||
default='/json',
|
||||
help='URL for IPA JSON RPC, relative to IPA base URL'),
|
||||
cfg.IntOpt('ipa-connect-retries', default=1,
|
||||
help='How many times Designate will attempt to retry '
|
||||
'the connection to IPA before giving up'),
|
||||
cfg.BoolOpt('ipa-force-ns-use', default=False,
|
||||
help='IPA requires that a specified '
|
||||
'name server or SOA MNAME is resolvable - if this '
|
||||
'option is set, Designate will force IPA to use a '
|
||||
'given name server even if it is not resolvable'),
|
||||
cfg.StrOpt('ipa-version', default='2.65',
|
||||
help='IPA RPC JSON version')
|
||||
]
|
||||
|
||||
return [(group, opts)]
|
||||
|
||||
def start(self):
|
||||
LOG.debug('IPABackend start')
|
||||
self.request = requests.Session()
|
||||
|
|
|
@ -24,17 +24,7 @@ from designate.backend import base
|
|||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
CFG_GRP = 'backend:multi'
|
||||
|
||||
cfg.CONF.register_group(cfg.OptGroup(
|
||||
name=CFG_GRP, title="Configuration for multi-backend Backend"
|
||||
))
|
||||
|
||||
cfg.CONF.register_opts([
|
||||
cfg.StrOpt('master', default='fake', help='Master backend'),
|
||||
cfg.StrOpt('slave', default='fake', help='Slave backend'),
|
||||
], group=CFG_GRP)
|
||||
CFG_GROUP = 'backend:multi'
|
||||
|
||||
|
||||
class MultiBackend(base.Backend):
|
||||
|
@ -59,12 +49,25 @@ class MultiBackend(base.Backend):
|
|||
"""
|
||||
__plugin_name__ = 'multi'
|
||||
|
||||
@classmethod
|
||||
def get_cfg_opts(cls):
|
||||
group = cfg.OptGroup(
|
||||
name=CFG_GROUP, title="Configuration for multi-backend Backend"
|
||||
)
|
||||
|
||||
opts = [
|
||||
cfg.StrOpt('master', default='fake', help='Master backend'),
|
||||
cfg.StrOpt('slave', default='fake', help='Slave backend'),
|
||||
]
|
||||
|
||||
return [(group, opts)]
|
||||
|
||||
def __init__(self, central_service):
|
||||
super(MultiBackend, self).__init__(central_service)
|
||||
self.central = central_service
|
||||
self.master = backend.get_backend(cfg.CONF[CFG_GRP].master,
|
||||
self.master = backend.get_backend(cfg.CONF[CFG_GROUP].master,
|
||||
central_service)
|
||||
self.slave = backend.get_backend(cfg.CONF[CFG_GRP].slave,
|
||||
self.slave = backend.get_backend(cfg.CONF[CFG_GROUP].slave,
|
||||
central_service)
|
||||
|
||||
def start(self):
|
||||
|
|
|
@ -28,29 +28,7 @@ from designate.openstack.common import log as logging
|
|||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
CFG_GRP = 'backend:nsd4slave'
|
||||
|
||||
cfg.CONF.register_group(
|
||||
cfg.OptGroup(name=CFG_GRP, title='Configuration for NSD4-slave backend')
|
||||
)
|
||||
|
||||
cfg.CONF.register_opts([
|
||||
cfg.StrOpt('keyfile', default='/etc/nsd/nsd_control.key',
|
||||
help='Keyfile to use when connecting to the NSD4 servers over '
|
||||
'SSL'),
|
||||
cfg.StrOpt('certfile', default='/etc/nsd/nsd_control.pem',
|
||||
help='Certfile to use when connecting to the NSD4 servers over '
|
||||
'SSL'),
|
||||
cfg.ListOpt('servers',
|
||||
help='Comma-separated list of servers to control, in '
|
||||
' <host>:<port> format. If <port> is omitted, '
|
||||
' the default 8952 is used.'),
|
||||
cfg.StrOpt('pattern', default='slave',
|
||||
help='Pattern to use when creating zones on the NSD4 servers. '
|
||||
'This pattern must be identically configured on all NSD4 '
|
||||
'servers.'),
|
||||
], group=CFG_GRP)
|
||||
|
||||
CFG_GROUP = 'backend:nsd4slave'
|
||||
DEFAULT_PORT = 8952
|
||||
|
||||
|
||||
|
@ -58,9 +36,34 @@ class NSD4SlaveBackend(base.Backend):
|
|||
__plugin__name__ = 'nsd4slave'
|
||||
NSDCT_VERSION = 'NSDCT1'
|
||||
|
||||
@classmethod
|
||||
def get_cfg_opts(cls):
|
||||
group = cfg.OptGroup(
|
||||
name=CFG_GROUP, title="Configuration for NSD4-slave backend"
|
||||
)
|
||||
|
||||
opts = [
|
||||
cfg.StrOpt('keyfile', default='/etc/nsd/nsd_control.key',
|
||||
help='Keyfile to use when connecting to the NSD4 '
|
||||
'servers over SSL'),
|
||||
cfg.StrOpt('certfile', default='/etc/nsd/nsd_control.pem',
|
||||
help='Certfile to use when connecting to the NSD4 '
|
||||
'servers over SSL'),
|
||||
cfg.ListOpt('servers',
|
||||
help='Comma-separated list of servers to control, in '
|
||||
' <host>:<port> format. If <port> is omitted, '
|
||||
' the default 8952 is used.'),
|
||||
cfg.StrOpt('pattern', default='slave',
|
||||
help='Pattern to use when creating zones on the NSD4 '
|
||||
'servers. This pattern must be identically '
|
||||
'configured on all NSD4 servers.'),
|
||||
]
|
||||
|
||||
return [(group, opts)]
|
||||
|
||||
def __init__(self, central_service):
|
||||
self._keyfile = cfg.CONF[CFG_GRP].keyfile
|
||||
self._certfile = cfg.CONF[CFG_GRP].certfile
|
||||
self._keyfile = cfg.CONF[CFG_GROUP].keyfile
|
||||
self._certfile = cfg.CONF[CFG_GROUP].certfile
|
||||
# Make sure keyfile and certfile are readable to avoid cryptic SSL
|
||||
# errors later
|
||||
if not os.access(self._keyfile, os.R_OK):
|
||||
|
@ -69,10 +72,10 @@ class NSD4SlaveBackend(base.Backend):
|
|||
if not os.access(self._certfile, os.R_OK):
|
||||
raise exceptions.NSD4SlaveBackendError(
|
||||
'Certfile %s missing or permission denied' % self._certfile)
|
||||
self._pattern = cfg.CONF[CFG_GRP].pattern
|
||||
self._pattern = cfg.CONF[CFG_GROUP].pattern
|
||||
try:
|
||||
self._servers = [self._parse_server(cfg_server)
|
||||
for cfg_server in cfg.CONF[CFG_GRP].servers]
|
||||
for cfg_server in cfg.CONF[CFG_GROUP].servers]
|
||||
except TypeError:
|
||||
raise exceptions.ConfigurationError('No NSD4 servers defined')
|
||||
|
||||
|
|
|
@ -37,21 +37,6 @@ LOG = logging.getLogger(__name__)
|
|||
CONF = cfg.CONF
|
||||
TSIG_SUPPORTED_ALGORITHMS = ['hmac-md5']
|
||||
|
||||
CONF.register_group(cfg.OptGroup(
|
||||
name='backend:powerdns', title="Configuration for Powerdns Backend"
|
||||
))
|
||||
|
||||
CONF.register_opts([
|
||||
cfg.StrOpt('domain-type', default='NATIVE', help='PowerDNS Domain Type'),
|
||||
cfg.ListOpt('also-notify', default=[], help='List of additional IPs to '
|
||||
'send NOTIFYs to'),
|
||||
] + options.database_opts, group='backend:powerdns')
|
||||
|
||||
# Overide the default DB connection registered above, to avoid name conflicts
|
||||
# between the Designate and PowerDNS databases.
|
||||
CONF.set_default('connection', 'sqlite:///$state_path/powerdns.sqlite',
|
||||
group='backend:powerdns')
|
||||
|
||||
|
||||
def _map_col(keys, col):
|
||||
return dict([(keys[i], col[i]) for i in range(len(keys))])
|
||||
|
@ -60,6 +45,27 @@ def _map_col(keys, col):
|
|||
class PowerDNSBackend(base.Backend):
|
||||
__plugin_name__ = 'powerdns'
|
||||
|
||||
@classmethod
|
||||
def get_cfg_opts(cls):
|
||||
group = cfg.OptGroup(
|
||||
name='backend:powerdns', title="Configuration for PowerDNS Backend"
|
||||
)
|
||||
|
||||
opts = [
|
||||
cfg.StrOpt('domain-type', default='NATIVE',
|
||||
help='PowerDNS Domain Type'),
|
||||
cfg.ListOpt('also-notify', default=[],
|
||||
help='List of additional IPs to send NOTIFYs to'),
|
||||
] + options.database_opts
|
||||
|
||||
# TODO(kiall):
|
||||
# Overide the default DB connection registered above, to avoid name
|
||||
# conflicts between the Designate and PowerDNS databases.
|
||||
# CONF.set_default('connection',
|
||||
# 'sqlite:///$state_path/powerdns.sqlite',
|
||||
# group='backend:powerdns')
|
||||
return [(group, opts)]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(PowerDNSBackend, self).__init__(*args, **kwargs)
|
||||
|
||||
|
|
|
@ -30,22 +30,6 @@ from designate.sqlalchemy import session
|
|||
LOG = logging.getLogger(__name__)
|
||||
CONF = cfg.CONF
|
||||
|
||||
OPTS = [
|
||||
cfg.ListOpt('masters', help="Master servers from which to transfer from."),
|
||||
]
|
||||
|
||||
CONF.register_group(cfg.OptGroup(
|
||||
name='backend:powerdns_mdns',
|
||||
title="Configuration for PowerDNS MDNS Backend"
|
||||
))
|
||||
|
||||
CONF.register_opts(OPTS + options.database_opts, group='backend:powerdns_mdns')
|
||||
|
||||
# Overide the default DB connection registered above, to avoid name conflicts
|
||||
# between the Designate and PowerDNS databases.
|
||||
CONF.set_default('connection', 'sqlite:///$state_path/powerdns_mdns.sqlite',
|
||||
group='backend:powerdns_mdns')
|
||||
|
||||
|
||||
def _map_col(keys, col):
|
||||
return dict([(keys[i], col[i]) for i in range(len(keys))])
|
||||
|
@ -54,6 +38,26 @@ def _map_col(keys, col):
|
|||
class PowerDNSMDNSBackend(base.Backend):
|
||||
__plugin_name__ = 'powerdns_mdns'
|
||||
|
||||
@classmethod
|
||||
def get_cfg_opts(cls):
|
||||
group = cfg.OptGroup(
|
||||
name='backend:powerdns_mdns',
|
||||
title="Configuration for PowerDNS MDNS Backend"
|
||||
)
|
||||
|
||||
opts = [
|
||||
cfg.ListOpt('masters',
|
||||
help="Master servers from which to transfer from."),
|
||||
] + options.database_opts
|
||||
|
||||
# TODO(kiall):
|
||||
# Overide the default DB connection registered above, to avoid name
|
||||
# conflicts between the Designate and PowerDNS databases.
|
||||
# CONF.set_default('connection',
|
||||
# 'sqlite:///$state_path/powerdns.sqlite',
|
||||
# group='backend:powerdns')
|
||||
return [(group, opts)]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(PowerDNSMDNSBackend, self).__init__(*args, **kwargs)
|
||||
|
||||
|
|
|
@ -21,17 +21,15 @@ from oslo.db.sqlalchemy.migration_cli import manager as migration_manager
|
|||
|
||||
from designate.openstack.common import log as logging
|
||||
from designate.manage import base
|
||||
|
||||
from designate import utils
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
REPOSITORY = os.path.abspath(os.path.join(os.path.dirname(__file__), '..',
|
||||
'backend', 'impl_powerdns',
|
||||
'migrate_repo'))
|
||||
cfg.CONF.import_opt('connection', 'designate.backend.impl_powerdns',
|
||||
group='backend:powerdns')
|
||||
|
||||
CONF = cfg.CONF
|
||||
utils.register_plugin_opts()
|
||||
|
||||
|
||||
def get_manager():
|
||||
|
|
|
@ -18,11 +18,14 @@ import abc
|
|||
import six
|
||||
from stevedore import driver
|
||||
from stevedore import enabled
|
||||
from stevedore import extension
|
||||
from oslo.config import cfg
|
||||
|
||||
from designate.openstack.common import log as logging
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
CONF = cfg.CONF
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
|
@ -53,6 +56,50 @@ class Plugin(object):
|
|||
def get_plugin_type(cls):
|
||||
return cls.__plugin_type__
|
||||
|
||||
@classmethod
|
||||
def get_cfg_opts(cls):
|
||||
"""Get any static configuration options
|
||||
|
||||
Returns an array of tuples in the form:
|
||||
|
||||
[(group1, [Option1, Option2]), (group2, [Option1, Option2])]
|
||||
"""
|
||||
return []
|
||||
|
||||
@classmethod
|
||||
def get_extra_cfg_opts(cls):
|
||||
"""Get any dynamically built configuration options
|
||||
|
||||
Returns an array of tuples in the form:
|
||||
|
||||
[(group1, [Option1, Option2]), (group2, [Option1, Option2])]
|
||||
"""
|
||||
return []
|
||||
|
||||
@classmethod
|
||||
def register_cfg_opts(cls, namespace):
|
||||
mgr = extension.ExtensionManager(namespace)
|
||||
|
||||
for e in mgr:
|
||||
for group, opts in e.plugin.get_cfg_opts():
|
||||
if isinstance(group, six.string_types):
|
||||
group = cfg.OptGroup(name=group)
|
||||
|
||||
CONF.register_group(group)
|
||||
CONF.register_opts(opts, group=group)
|
||||
|
||||
@classmethod
|
||||
def register_extra_cfg_opts(cls, namespace):
|
||||
mgr = extension.ExtensionManager(namespace)
|
||||
|
||||
for e in mgr:
|
||||
for group, opts in e.plugin.get_extra_cfg_opts():
|
||||
if isinstance(group, six.string_types):
|
||||
group = cfg.OptGroup(name=group)
|
||||
|
||||
CONF.register_group(group)
|
||||
CONF.register_opts(opts, group=group)
|
||||
|
||||
|
||||
class DriverPlugin(Plugin):
|
||||
"""
|
||||
|
|
|
@ -20,6 +20,8 @@ cfg.CONF.register_group(cfg.OptGroup(
|
|||
))
|
||||
|
||||
OPTS = [
|
||||
cfg.ListOpt('backends', default=[],
|
||||
help='List of enabled backend drivers'),
|
||||
cfg.IntOpt('workers', default=None,
|
||||
help='Number of Pool Manager worker processes to spawn'),
|
||||
cfg.StrOpt('pool-id', default='794ccc2c-d751-44fe-b57f-8894c9f5c842',
|
||||
|
|
|
@ -1,136 +0,0 @@
|
|||
# Copyright 2014 eBay Inc.
|
||||
#
|
||||
# Author: Ron Rickard <rrickard@ebaysf.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
import re
|
||||
|
||||
from oslo.config import iniparser
|
||||
|
||||
from designate import utils
|
||||
|
||||
|
||||
GLOBAL_SECTION_NAME_LABEL = '*'
|
||||
SECTION_NAME_PREFIX = 'backend'
|
||||
SECTION_NAME_SEPARATOR = ':'
|
||||
UUID_PATTERN = '-'.join([
|
||||
'[0-9A-Fa-f]{8}',
|
||||
'[0-9A-Fa-f]{4}',
|
||||
'[0-9A-Fa-f]{4}',
|
||||
'[0-9A-Fa-f]{4}',
|
||||
'[0-9A-Fa-f]{12}'
|
||||
|
||||
])
|
||||
SECTION_PATTERN = SECTION_NAME_SEPARATOR.join([
|
||||
'^%s' % SECTION_NAME_PREFIX,
|
||||
'(.*)',
|
||||
'(%s)' % UUID_PATTERN
|
||||
])
|
||||
SECTION_LABELS = [
|
||||
'backend',
|
||||
'server_id'
|
||||
]
|
||||
|
||||
|
||||
class SectionNameParser(iniparser.BaseParser):
|
||||
"""
|
||||
Used to retrieve the configuration file section names and parse the names.
|
||||
"""
|
||||
|
||||
def __init__(self, pattern, labels):
|
||||
super(SectionNameParser, self).__init__()
|
||||
self.regex = re.compile(pattern)
|
||||
self.labels = labels
|
||||
self.sections = []
|
||||
|
||||
def assignment(self, key, value):
|
||||
pass
|
||||
|
||||
def new_section(self, section):
|
||||
match = self.regex.match(section)
|
||||
if match:
|
||||
value = {
|
||||
'name': section
|
||||
}
|
||||
index = 1
|
||||
for label in self.labels:
|
||||
value[label] = match.group(index)
|
||||
index += 1
|
||||
self.sections.append(value)
|
||||
|
||||
def parse(self, filename):
|
||||
with open(filename) as f:
|
||||
return super(SectionNameParser, self).parse(f)
|
||||
|
||||
@classmethod
|
||||
def find_sections(cls, filename, pattern, labels):
|
||||
parser = cls(pattern, labels)
|
||||
parser.parse(filename)
|
||||
|
||||
return parser.sections
|
||||
|
||||
|
||||
def find_server_sections():
|
||||
"""
|
||||
Find the server specific backend section names.
|
||||
|
||||
A server specific backend section name is:
|
||||
|
||||
[backend:<backend_driver>:<server_id>]
|
||||
"""
|
||||
config_files = utils.find_config('designate.conf')
|
||||
|
||||
all_sections = []
|
||||
for filename in config_files:
|
||||
sections = SectionNameParser.find_sections(
|
||||
filename, SECTION_PATTERN, SECTION_LABELS)
|
||||
all_sections.extend(sections)
|
||||
|
||||
return all_sections
|
||||
|
||||
|
||||
def _generate_section_name(backend_driver, label):
|
||||
"""
|
||||
Generate the section name.
|
||||
|
||||
A section name is:
|
||||
|
||||
[backend:<backend_driver>:<label>]
|
||||
"""
|
||||
return SECTION_NAME_SEPARATOR.join([
|
||||
SECTION_NAME_PREFIX,
|
||||
backend_driver,
|
||||
label
|
||||
])
|
||||
|
||||
|
||||
def generate_global_section_name(backend_driver):
|
||||
"""
|
||||
Generate the global backend section name.
|
||||
|
||||
A global backend section name is:
|
||||
|
||||
[backend:<backend_driver>:*]
|
||||
"""
|
||||
return _generate_section_name(backend_driver, GLOBAL_SECTION_NAME_LABEL)
|
||||
|
||||
|
||||
def generate_server_section_name(backend_driver, server_id):
|
||||
"""
|
||||
Generate the server specific backend section name.
|
||||
|
||||
A server specific backend section name is:
|
||||
|
||||
[backend:<backend_driver>:<server_id>]
|
||||
"""
|
||||
return _generate_section_name(backend_driver, server_id)
|
|
@ -28,7 +28,6 @@ from designate.context import DesignateContext
|
|||
from designate.openstack.common import log as logging
|
||||
from designate.openstack.common import threadgroup
|
||||
from designate.pool_manager import cache
|
||||
import designate.pool_manager.backend_section_name as backend_section_name
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
@ -93,7 +92,15 @@ class Service(service.RPCService):
|
|||
self.delay = cfg.CONF['service:pool_manager'].poll_delay
|
||||
|
||||
self.server_backends = []
|
||||
sections = backend_section_name.find_server_sections()
|
||||
|
||||
sections = []
|
||||
for backend_name in cfg.CONF['service:pool_manager'].backends:
|
||||
server_ids = cfg.CONF['backend:%s' % backend_name].server_ids
|
||||
|
||||
for server_id in server_ids:
|
||||
sections.append({"backend": backend_name,
|
||||
"server_id": server_id})
|
||||
|
||||
for section in sections:
|
||||
backend_driver = section['backend']
|
||||
server_id = section['server_id']
|
||||
|
|
|
@ -339,6 +339,7 @@ class TestCase(base.BaseTestCase):
|
|||
|
||||
# "Read" Configuration
|
||||
self.CONF([], project='designate')
|
||||
utils.register_plugin_opts()
|
||||
|
||||
self.useFixture(PolicyFixture())
|
||||
self.network_api = NetworkAPIFixture()
|
||||
|
|
|
@ -91,6 +91,17 @@ def read_config(prog, argv):
|
|||
cfg.CONF(argv[1:], project='designate', prog=prog,
|
||||
default_config_files=config_files)
|
||||
|
||||
register_plugin_opts()
|
||||
|
||||
|
||||
def register_plugin_opts():
|
||||
# Avoid circular dependency imports
|
||||
from designate import plugin
|
||||
|
||||
# Register Backend Plugin Config Options
|
||||
plugin.Plugin.register_cfg_opts('designate.backend')
|
||||
plugin.Plugin.register_extra_cfg_opts('designate.backend')
|
||||
|
||||
|
||||
def resource_string(*args):
|
||||
if len(args) == 0:
|
||||
|
|
|
@ -132,6 +132,7 @@ debug = False
|
|||
# Pool Manager Service
|
||||
#-----------------------
|
||||
[service:pool_manager]
|
||||
#backends = bind9_pool
|
||||
#workers = None
|
||||
#pool_name = default
|
||||
#threshold-percentage = 100
|
||||
|
@ -267,7 +268,8 @@ debug = False
|
|||
#-----------------------
|
||||
# Global Bind9 Pool Backend
|
||||
#-----------------------
|
||||
[backend:bind9_pool:*]
|
||||
[backend:bind9_pool]
|
||||
#server_ids = 6a5032b6-2d96-43ee-b25b-7d784e2bf3b2
|
||||
#masters = 127.0.0.1:5354
|
||||
#rndc_host = 127.0.0.1
|
||||
#rndc_port = 953
|
||||
|
|
Loading…
Reference in New Issue