From 76f449e7a991c83fc344ee54ac9fa2b80e7ae5b5 Mon Sep 17 00:00:00 2001 From: arrance Date: Sat, 3 Sep 2016 14:38:16 -0400 Subject: [PATCH] Initial skeleton code commit. --- src/lib/charm/__init__.py | 0 src/lib/charm/openstack/trove.py | 483 ++++++++++++++++++++ src/templates/mitaka/README.md | 2 +- src/templates/mitaka/api-paste.ini | 43 ++ src/templates/mitaka/trove-conductor.conf | 62 +++ src/templates/mitaka/trove-guestagent.conf | 6 + src/templates/mitaka/trove-taskmanager.conf | 104 +++++ src/templates/mitaka/trove.conf | 122 +++++ 8 files changed, 821 insertions(+), 1 deletion(-) create mode 100644 src/lib/charm/__init__.py create mode 100644 src/lib/charm/openstack/trove.py create mode 100644 src/templates/mitaka/api-paste.ini create mode 100644 src/templates/mitaka/trove-conductor.conf create mode 100644 src/templates/mitaka/trove-guestagent.conf create mode 100644 src/templates/mitaka/trove-taskmanager.conf create mode 100644 src/templates/mitaka/trove.conf diff --git a/src/lib/charm/__init__.py b/src/lib/charm/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/lib/charm/openstack/trove.py b/src/lib/charm/openstack/trove.py new file mode 100644 index 0000000..16df3ad --- /dev/null +++ b/src/lib/charm/openstack/trove.py @@ -0,0 +1,483 @@ +# Copyright 2016 TransCirrus Inc. +# +# 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 contextlib +import os +import subprocess +import uuid + +import charmhelpers.contrib.openstack.utils as ch_utils +import openstack_adapters as openstack_adapters +import charms_openstack.charm as openstack_charm +import charms_openstack.ip as os_ip +import charmhelpers.core.decorators as decorators +import charmhelpers.core.hookenv as hookenv +import charmhelpers.core.host as host + +TROVE_DIR = '/etc/trove' +TROVE_DEFAULT = '/etc/default/openstack' +TROVE_CONF = TROVE_DIR + '/trove.conf' +#RC_FILE = '/root/novarc' + + +# select the default release function to choose the right Charm class +openstack_charm.use_defaults('charm.default-select-release') + + +#def render_sink_configs(interfaces_list): +# """Use the singleton from the DesignateCharm to render sink configs + +# @param interfaces_list: List of instances of interface classes. +# @returns: None +# """ +# configs = [NOVA_SINK_FILE, NEUTRON_SINK_FILE, DESIGNATE_DEFAULT] +# DesignateCharm.singleton.render_with_interfaces( +# interfaces_list, +# configs=configs) + + +# Get database URIs for the two designate databases +@openstack_adapters.adapter_property('shared-db') +def trove_uri(db): + """URI for designate DB""" + return db.get_uri(prefix='trove') + + +#@openstack_adapters.adapter_property('shared-db') +#def designate_pool_uri(db): +# """URI for designate pool DB""" +# return db.get_uri(prefix='dpm') + + +#@openstack_adapters.adapter_property('dns') +#def slave_ips(dns): +# """List of DNS slave address infoprmation + +# @returns: list [{'unit': unitname, 'address': 'address'}, +# ...] +# """ +# return dns.relation.slave_ips() + + +@openstack_adapters.adapter_property('dns') +def pool_config(dns): + """List of DNS slave information from Juju attached DNS slaves + + Creates a dict for each backends and returns a list of those dicts. + The designate config file has a section per backend. The template uses + the nameserver and pool_target names to create a section for each + backend + + @returns: list [{'nameserver': name, 'pool_target': name, + 'address': slave_ip_addr}, + ...] + """ + pconfig = [] + for slave in dns.slave_ips: + unit_name = slave['unit'].replace('/', '_').replace('-', '_') + pconfig.append({ + 'nameserver': 'nameserver_{}'.format(unit_name), + 'pool_target': 'nameserver_{}'.format(unit_name), + 'address': slave['address'], + }) + return pconfig + + +@openstack_adapters.adapter_property('dns') +def pool_targets(dns): + """List of pool_target section names + + @returns: str Comma delimited list of pool_target section names + """ + return ', '.join([s['pool_target'] for s in dns.pool_config]) + + +@openstack_adapters.adapter_property('dns') +def slave_addresses(dns): + """List of slave IP addresses + + @returns: str Comma delimited list of slave IP addresses + """ + return ', '.join(['{}:53'.format(s['address']) + for s in dns.pool_config]) + + +@openstack_adapters.adapter_property('dns') +def rndc_info(dns): + """Rndc key and algorith in formation. + + @returns: dict {'algorithm': rndc_algorithm, + 'secret': rndc_secret_digest} + """ + return dns.relation.rndc_info + + +## configuration adapter custom properties + +@openstack_adapters.config_property +def pool_config(config): + """List of DNS slave information from user defined config + + Creates a dict for each backends and returns a list of those dicts. + The designate config file has a section per backend. The template uses + the nameserver and pool_target names to create a section for each + backend. + + @returns: list [{'nameserver': name, + 'pool_target': name, + 'address': slave_ip_addr, + 'rndc_key_file': rndc_key_file}, + ...] + """ + pconfig = [] + for entry in config.dns_slaves.split(): + address, port, key = entry.split(':') + unit_name = address.replace('.', '_') + pconfig.append({ + 'nameserver': 'nameserver_{}'.format(unit_name), + 'pool_target': 'nameserver_{}'.format(unit_name), + 'address': address, + 'rndc_key_file': '/etc/designate/rndc_{}.key'.format( + unit_name), + }) + return pconfig + + +@openstack_adapters.config_property +def pool_targets(config): + """List of pool_target section names + + @returns: str Comma delimited list of pool_target section names + """ + return ', '.join([s['pool_target'] for s in config.pool_config]) + + +@openstack_adapters.config_property +def slave_addresses(config): + """List of slave IP addresses + + @returns: str Comma delimited list of slave IP addresses + """ + return ', '.join(['{}:53'.format(s['address']) + for s in config.pool_config]) + + +@openstack_adapters.config_property +def nova_domain_id(config): + """Returns the id of the domain corresponding to the user supplied + 'nova-domain' + + @returns nova domain id + """ + domain = hookenv.config('nova-domain') + if domain: + return DesignateCharm.get_domain_id(domain) + return None + + +@openstack_adapters.config_property +def neutron_domain_id(config): + """Returns the id of the domain corresponding to the user supplied + 'neutron-domain' + + @returns neutron domain id + """ + domain = hookenv.config('neutron-domain') + if domain: + return DesignateCharm.get_domain_id(domain) + return None + + +@openstack_adapters.config_property +def nova_conf_args(config): + """Returns config file directive to point daemons at nova config file. + These directives are designed to be used in /etc/default/ files + + @returns startup config file option + """ + daemon_arg = '' + if os.path.exists(NOVA_SINK_FILE): + daemon_arg = '--config-file={}'.format(NOVA_SINK_FILE) + return daemon_arg + + +@openstack_adapters.config_property +def neutron_conf_args(config): + """Returns config file directive to point daemons at neutron config + file. These directives are designed to be used in /etc/default/ files + + @returns startup config file option + """ + daemon_arg = '' + if os.path.exists(NEUTRON_SINK_FILE): + daemon_arg = '--config-file={}'.format(NEUTRON_SINK_FILE) + return daemon_arg + + +@openstack_adapters.config_property +def rndc_master_ip(config): + """Returns IP address slave DNS slave should use to query master + """ + return os_ip.resolve_address(endpoint_type=os_ip.INTERNAL) + + +class DesignateCharm(openstack_charm.HAOpenStackCharm): + """Designate charm""" + + name = 'designate' + packages = ['designate-agent', 'designate-api', 'designate-central', + 'designate-common', 'designate-mdns', + 'designate-pool-manager', 'designate-sink', + 'designate-zone-manager', 'bind9utils', 'python-apt'] + + services = ['designate-mdns', 'designate-zone-manager', + 'designate-agent', 'designate-pool-manager', + 'designate-central', 'designate-sink', + 'designate-api'] + + api_ports = { + 'designate-api': { + os_ip.PUBLIC: 9001, + os_ip.ADMIN: 9001, + os_ip.INTERNAL: 9001, + } + } + + required_relations = ['shared-db', 'amqp', 'identity-service', + 'dns-backend'] + + restart_map = { + '/etc/default/openstack': services, + '/etc/designate/designate.conf': services, + '/etc/designate/rndc.key': services, + '/etc/designate/conf.d/nova_sink.cfg': services, + '/etc/designate/conf.d/neutron_sink.cfg': services, + '/etc/designate/pools.yaml': [''], + RC_FILE: [''], + } + service_type = 'designate' + default_service = 'designate-api' + sync_cmd = ['designate-manage', 'database', 'sync'] + + ha_resources = ['vips', 'haproxy'] + release = 'mitaka' + + def get_amqp_credentials(self): + """Provide the default amqp username and vhost as a tuple. + + :returns (username, host): two strings to send to the amqp provider. + """ + return ('designate', 'openstack') + + def get_database_setup(self): + """Provide the default database credentials as a list of 3-tuples + + returns a structure of: + [ + {'database': , + 'username': , + 'hostname': + 'prefix': , }, + ] + + :returns [{'database': ...}, ...]: credentials for multiple databases + """ + ip = hookenv.unit_private_ip() + return [ + dict( + database='designate', + username='designate', + hostname=ip, + prefix='designate'), + dict( + database='dpm', + username='dpm', + prefix='dpm', + hostname=ip) + ] + + def render_base_config(self, interfaces_list): + """Render initial config to bootstrap Designate service + + @returns None + """ + configs = [RC_FILE, DESIGNATE_CONF, RNDC_KEY_CONF, DESIGNATE_DEFAULT] + if self.haproxy_enabled(): + configs.append(self.HAPROXY_CONF) + self.render_with_interfaces( + interfaces_list, + configs=configs) + + def render_full_config(self, interfaces_list): + """Render all config for Designate service + + @returns None + """ + # Render base config first to ensure Designate API is responding as + # sink configs rely on it. + self.render_base_config(interfaces_list) + self.render_with_interfaces(interfaces_list) + + def write_key_file(self, unit_name, key): + """Write rndc keyfile for given unit_name + + @param unit_name: str Name of unit using key + @param key: str RNDC key + @returns None + """ + key_file = '/etc/designate/rndc_{}.key'.format(unit_name) + template = ('key "rndc-key" {{\n algorithm hmac-md5;\n ' + 'secret "{}";\n}};') + host.write_file( + key_file, + str.encode(template.format(key)), + owner='root', + group='designate', + perms=0o440) + + def render_rndc_keys(self): + """Render the rndc keys supplied via user config + + @returns None + """ + slaves = hookenv.config('dns-slaves') or '' + for entry in slaves.split(): + address, port, key = entry.split(':') + unit_name = address.replace('.', '_') + self.write_key_file(unit_name, key) + + @classmethod + def get_domain_id(cls, domain): + """Return the domain ID for a given domain name + + @param domain: Domain name + @returns domain_id + """ + if domain: + cls.ensure_api_responding() + get_cmd = ['reactive/designate_utils.py', 'domain-get', + '--domain-name', domain] + output = subprocess.check_output(get_cmd) + if output: + return output.decode('utf8').strip() + return None + + @classmethod + def create_domain(cls, domain, email): + """Create a domain + + @param domain: The name of the domain you are creating. The name must + end with a full stop. + @param email: An email address of the person responsible for the + domain. + @returns None + """ + cls.ensure_api_responding() + create_cmd = ['reactive/designate_utils.py', 'domain-create', + '--domain-name', domain, '--email', email] + subprocess.check_call(create_cmd) + + @classmethod + def create_server(cls, nsname): + """ create a nameserver entry with the supplied name + + @param nsname: Name of NameserverS record + @returns None + """ + cls.ensure_api_responding() + create_cmd = ['reactive/designate_utils.py', 'server-create', + '--server-name', nsname] + subprocess.check_call(create_cmd) + + @classmethod + def domain_init_done(cls): + """Query leader db to see if domain creation is donei + + @returns boolean""" + return hookenv.leader_get(attribute='domain-init-done') + + @classmethod + @decorators.retry_on_exception( + 10, base_delay=5, exc_type=subprocess.CalledProcessError) + def ensure_api_responding(cls): + """Check that the api service is responding. + + The retry_on_exception decorator will cause this method to be called + until it succeeds or retry limit is exceeded""" + hookenv.log('Checking API service is responding', + level=hookenv.WARNING) + check_cmd = ['reactive/designate_utils.py', 'server-list'] + subprocess.check_call(check_cmd) + + @classmethod + @contextlib.contextmanager + def check_zone_ids(cls, nova_domain_name, neutron_domain_name): + zone_org_ids = { + 'nova-domain-id': cls.get_domain_id(nova_domain_name), + 'neutron-domain-id': cls.get_domain_id(neutron_domain_name), + } + yield + zone_ids = { + 'nova-domain-id': cls.get_domain_id(nova_domain_name), + 'neutron-domain-id': cls.get_domain_id(neutron_domain_name), + } + if zone_org_ids != zone_ids: + # Update leader-db to trigger peers to rerender configs + # as sink files will need updating with new domain ids + # Use host ID and current time UUID to help with debugging + hookenv.leader_set({'domain-init-done': uuid.uuid1()}) + + @classmethod + def create_initial_servers_and_domains(cls): + """Create the nameserver entry and domains based on the charm user + supplied config + + @returns None + """ + if hookenv.is_leader(): + cls.ensure_api_responding() + nova_domain_name = hookenv.config('nova-domain') + neutron_domain_name = hookenv.config('neutron-domain') + with cls.check_zone_ids(nova_domain_name, neutron_domain_name): + if hookenv.config('nameservers'): + for ns in hookenv.config('nameservers').split(): + cls.create_server(ns) + else: + hookenv.log('No nameserver specified, skipping creation of' + 'nova and neutron domains', + level=hookenv.WARNING) + return + if nova_domain_name: + cls.create_domain( + nova_domain_name, + hookenv.config('nova-domain-email')) + if neutron_domain_name: + cls.create_domain( + neutron_domain_name, + hookenv.config('neutron-domain-email')) + + def update_pools(self): + # designate-manage communicates with designate via message bus so no + # need to set OS_ vars + if hookenv.is_leader(): + cmd = ['designate-manage', 'pool', 'update'] + subprocess.check_call(cmd) + + def custom_assess_status_check(self): + if (not hookenv.config('nameservers') and + (hookenv.config('nova-domain') or + hookenv.config('neutron-domain'))): + return 'blocked', ('nameservers must be set when specifying' + ' nova-domain or neutron-domain') + return None, None \ No newline at end of file diff --git a/src/templates/mitaka/README.md b/src/templates/mitaka/README.md index 8b13789..2900a4d 100644 --- a/src/templates/mitaka/README.md +++ b/src/templates/mitaka/README.md @@ -1 +1 @@ - +These are the prototype config files for the Trove service. diff --git a/src/templates/mitaka/api-paste.ini b/src/templates/mitaka/api-paste.ini new file mode 100644 index 0000000..ea3612b --- /dev/null +++ b/src/templates/mitaka/api-paste.ini @@ -0,0 +1,43 @@ +[composite:trove] +use = call:trove.common.wsgi:versioned_urlmap +/: versions +/v1.0: troveapi + +[app:versions] +paste.app_factory = trove.versions:app_factory + +[pipeline:troveapi] +pipeline = cors faultwrapper osprofiler authtoken authorization contextwrapper ratelimit extensions troveapp +#pipeline = debug extensions troveapp + +[filter:extensions] +paste.filter_factory = trove.common.extensions:factory + +[filter:authtoken] +paste.filter_factory = keystonemiddleware.auth_token:filter_factory + +[filter:authorization] +paste.filter_factory = trove.common.auth:AuthorizationMiddleware.factory + +[filter:cors] +paste.filter_factory = oslo_middleware.cors:filter_factory +oslo_config_project = trove + +[filter:contextwrapper] +paste.filter_factory = trove.common.wsgi:ContextMiddleware.factory + +[filter:faultwrapper] +paste.filter_factory = trove.common.wsgi:FaultWrapper.factory + +[filter:ratelimit] +paste.filter_factory = trove.common.limits:RateLimitingMiddleware.factory + +[filter:osprofiler] +paste.filter_factory = osprofiler.web:WsgiMiddleware.factory + +[app:troveapp] +paste.app_factory = trove.common.api:app_factory + +#Add this filter to log request and response for debugging +[filter:debug] +paste.filter_factory = trove.common.wsgi:Debug diff --git a/src/templates/mitaka/trove-conductor.conf b/src/templates/mitaka/trove-conductor.conf new file mode 100644 index 0000000..0695ffc --- /dev/null +++ b/src/templates/mitaka/trove-conductor.conf @@ -0,0 +1,62 @@ +[DEFAULT] +verbose = False +debug = False +trove_auth_url = http://0.0.0.0:5000/v2.0 +connection = sqlite:////var/lib/trove/trove.sqlite + + +# The manager class to use for conductor. (string value) +conductor_manager = trove.conductor.manager.Manager + +#===================== RPC Configuration ================================= + +# URL representing the messaging driver to use and its full configuration. +# If not set, we fall back to the 'rpc_backend' option and driver specific +# configuration. +#transport_url= + +# The messaging driver to use. Options include rabbit, qpid and zmq. +# Default is rabbit. (string value) +#rpc_backend=rabbit + +# The default exchange under which topics are scoped. May be +# overridden by an exchange name specified in the 'transport_url option. +control_exchange = trove + +[profiler] +# If False fully disable profiling feature. +#enabled = False +# If False doesn't trace SQL requests. +#trace_sqlalchemy = True + +[database] +connection = mysql://root:e1a2c042c828d3566d0a@localhost/trove + +[oslo_messaging_rabbit] +# The RabbitMQ broker address where a single node is used. (string value) +# Deprecated group/name - [DEFAULT]/rabbit_host +#rabbit_host=localhost + +# The RabbitMQ broker port where a single node is used. (integer value) +# Deprecated group/name - [DEFAULT]/rabbit_port +#rabbit_port=5672 + +# RabbitMQ HA cluster host:port pairs. (list value) +# Deprecated group/name - [DEFAULT]/rabbit_hosts +#rabbit_hosts=$rabbit_host:$rabbit_port + +# Connect over SSL for RabbitMQ. (boolean value) +# Deprecated group/name - [DEFAULT]/rabbit_use_ssl +#rabbit_use_ssl=false + +# The RabbitMQ userid. (string value) +# Deprecated group/name - [DEFAULT]/rabbit_userid +#rabbit_userid=guest + +# The RabbitMQ password. (string value) +# Deprecated group/name - [DEFAULT]/rabbit_password +#rabbit_password=f7999d1955c5014aa32c + +# The RabbitMQ virtual host. (string value) +# Deprecated group/name - [DEFAULT]/rabbit_virtual_host +#rabbit_virtual_host=/ diff --git a/src/templates/mitaka/trove-guestagent.conf b/src/templates/mitaka/trove-guestagent.conf new file mode 100644 index 0000000..1898453 --- /dev/null +++ b/src/templates/mitaka/trove-guestagent.conf @@ -0,0 +1,6 @@ +rabbit_host = controller +rabbit_password = RABBIT_PASS +nova_proxy_admin_user = admin +nova_proxy_admin_pass = ADMIN_PASS +nova_proxy_admin_tenant_name = service +trove_auth_url = http://controller:35357/v2.0 diff --git a/src/templates/mitaka/trove-taskmanager.conf b/src/templates/mitaka/trove-taskmanager.conf new file mode 100644 index 0000000..cd536ed --- /dev/null +++ b/src/templates/mitaka/trove-taskmanager.conf @@ -0,0 +1,104 @@ +[DEFAULT] +# Show more verbose log output (sets INFO log level output) +verbose = False + +# Show debugging output in logs (sets DEBUG log level output) +debug = False + +# Update the service and instance statuses if the instances fails to become +# active within the configured usage_timeout. +# usage_timeout = 600 +# restore_usage_timeout = 36000 +update_status_on_fail = True + +log_dir = /var/log/trove +trove_auth_url = http://controller:5000/v2.0 +nova_compute_url = http://controller:8774/v2 +cinder_url = http://controller:8776/v1 +swift_url = http://controller:8080/v1/AUTH_ +notifier_queue_hostname = controller +backend = rabbit + +# The default exchange under which topics are scoped. May be +# overridden by an exchange name specified in the 'transport_url option. +control_exchange = trove + +#DB Api Implementation +db_api_implementation = trove.db.sqlalchemy.api + +# Configuration options for talking to nova via the novaclient. +# These options are for an admin user in your keystone config. +# It proxy's the token received from the user to send to nova +# via this admin users creds, +# basically acting like the client via that proxy token. +nova_proxy_admin_user = admin +nova_proxy_admin_pass = ADMIN_PASS +nova_proxy_admin_tenant_name = service +taskmanager_manager = trove.taskmanager.manager.Manager + +# Region name of this node. Used when searching catalog. Default value is None. +os_region_name = RegionOne +# Service type to use when searching catalog. +nova_compute_service_type = compute +# Service type to use when searching catalog. +cinder_service_type = volumev2 +# Service type to use when searching catalog. +swift_service_type = object-store +# Service type to use when searching catalog. +heat_service_type = orchestration +# Service type to use when searching catalog. +neutron_service_type = network + +# Config options for enabling volume service +trove_volume_support = True +block_device_mapping = vdb +device_path = /dev/vdb +mount_point = /var/lib/mysql +volume_time_out=30 +server_delete_time_out=480 + +[mysql] +# Format (single port or port range): A, B-C +# where C greater than B +tcp_ports = 3306 +volume_support = True +device_path = /dev/vdb + +[redis] +# Format (single port or port range): A, B-C +# where C greater than B +tcp_ports = 6379 +# redis uses local storage +volume_support = False +# default device_path = None + +[cassandra] +tcp_ports = 7000, 7001, 9042, 9160 +volume_support = True +device_path = /dev/vdb + +[couchbase] +tcp_ports = 8091, 8092, 4369, 11209-11211, 21100-21199 +volume_support = True +device_path = /dev/vdb + +[mongodb] +volume_support = True +device_path = /dev/vdb + +[vertica] +tcp_ports = 5433, 5434, 22, 5444, 5450, 4803 +udp_ports = 5433, 4803, 4804, 6453 +volume_support = True +device_path = /dev/vdb +mount_point = /var/lib/vertica +taskmanager_strategy = trove.common.strategies.cluster.experimental.vertica.taskmanager.VerticaTaskManagerStrategy + + +[oslo_messaging_rabbit] +rabbit_host = controller +rabbit_userid = openstack +rabbit_password = RABBIT_PASS + +[database] +connection = mysql://trove:TROVE_DBPASS@controller/trove diff --git a/src/templates/mitaka/trove.conf b/src/templates/mitaka/trove.conf new file mode 100644 index 0000000..3e3f49f --- /dev/null +++ b/src/templates/mitaka/trove.conf @@ -0,0 +1,122 @@ +[DEFAULT] +auth_strategy = keystone +log_dir = /var/log/trove +trove_auth_url = http://controller:5000/v2.0 +nova_compute_url = http://controller:8774/v2 +cinder_url = http://controller:8776/v1 +swift_url = http://controller:8080/v1/AUTH_ +notifier_queue_hostname = controller + +# Show more verbose log output (sets INFO log level output) +verbose = False + +# Show debugging output in logs (sets DEBUG log level output) +debug = False + +# Address to bind the API server +bind_host = 0.0.0.0 + +# Port the bind the API server to +bind_port = 8779 + +rpc_backend = rabbit + +# Config option for showing the IP address that nova doles out +add_addresses = True +api_paste_config = /etc/trove/api-paste.ini + +control_exchange = trove + +#DB Api Implementation +db_api_implementation = "trove.db.sqlalchemy.api" + +# Region name of this node. Used when searching catalog. Default value is None. +os_region_name = RegionOne +# Service type to use when searching catalog. +nova_compute_service_type = compute +# Service type to use when searching catalog. +cinder_service_type = volumev2 +# Service type to use when searching catalog. +swift_service_type = object-store +# Service type to use when searching catalog. +heat_service_type = orchestration +# Service type to use when searching catalog. +neutron_service_type = network + +# Config options for enabling volume service +trove_volume_support = True +block_device_mapping = vdb +device_path = /dev/vdb +# Maximum volume size for an instance +max_accepted_volume_size = 10 +max_instances_per_tenant = 5 +# Maximum volume capacity (in GB) spanning across all trove volumes per tenant +max_volumes_per_tenant = 100 +max_backups_per_tenant = 5 +volume_time_out=30 + + + +[oslo_messaging_rabbit] +rabbit_host = controller +rabbit_userid = openstack +rabbit_password = RABBIT_PASS + +[database] +connection = mysql://trove:TROVE_DBPASS@controller/trove + +[mysql] +root_on_create = False +# Format (single port or port range): A, B-C +# where C greater than B +tcp_ports = 3306 +volume_support = True +device_path = /dev/vdb + +# Users to ignore for user create/list/delete operations +ignore_users = os_admin, root +ignore_dbs = mysql, information_schema, performance_schema + + +[redis] +tcp_ports = 6379 +#redis uses local storage +volume_support = False +# default device_path = None + +[cassandra] +tcp_ports = 7000, 7001, 9042, 9160 +volume_support = True +device_path = /dev/vdb + +[couchbase] +tcp_ports = 8091, 8092, 4369, 11209-11211, 21100-21199 +volume_support = True +device_path = /dev/vdb + +[mongodb] +tcp_ports = 2500, 27017 +volume_support = True +device_path = /dev/vdb +num_config_servers_per_cluster = 1 +num_query_routers_per_cluster = 1 + +[vertica] +tcp_ports = 5433, 5434, 22, 5444, 5450, 4803 +udp_ports = 5433, 4803, 4804, 6453 +volume_support = True +device_path = /dev/vdb +cluster_support = True +cluster_member_count = 3 +api_strategy = trove.common.strategies.cluster.experimental.vertica.api.VerticaAPIStrategy + + +[keystone_authtoken] +auth_uri = http://controller:5000 +auth_url = http://controller:35357 +auth_type = password +project_domain_name = default +user_domain_name = default +project_name = service +username = trove +password = TROVE_PASS