Retire project

Leave README around for those that follow.

http://lists.openstack.org/pipermail/openstack-discuss/2019-February/003186.html
http://lists.openstack.org/pipermail/openstack-discuss/2018-November/000057.html

Change-Id: Ia77e53a5b24153094d53c518beba911afa6f8c9b
This commit is contained in:
Ryan Beisner 2018-11-01 20:57:23 -05:00
parent 48b78e4aeb
commit 9679e95a17
No known key found for this signature in database
GPG Key ID: 952BACDC1C1A05FB
42 changed files with 7 additions and 2810 deletions

10
.gitignore vendored
View File

@ -1,10 +0,0 @@
build
layers
.tox
interfaces
builds
deps
.testrepository
__pycache__
*.pyc
.stestr

View File

@ -1,4 +0,0 @@
[gerrit]
host=review.openstack.org
port=29418
project=openstack/charm-trove.git

View File

@ -1,8 +0,0 @@
[DEFAULT]
test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \
OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \
OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-60} \
${PYTHON:-python} -m subunit.run discover -t ./ ./unit_tests $LISTOPT $IDOPTION
test_id_option=--load-list $IDFILE
test_list_option=--list

View File

@ -1,4 +1,3 @@
- project: - project:
templates: templates:
- python-charm-jobs - noop-jobs
- openstack-python35-jobs

201
LICENSE
View File

@ -1,201 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
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.

View File

@ -1 +1,6 @@
# charm-trove This project is no longer maintained.
The contents of this repository are still available in the Git
source code management system. To see the contents of this
repository before it reached its end of life, please check out the
previous commit with "git checkout HEAD^1".

View File

@ -1,4 +0,0 @@
# Requirements to build the charm
charm-tools
simplejson
flake8

View File

@ -1,89 +0,0 @@
# Overview
This charm provides the Trove (DBaaS) for an OpenStack Cloud.
# Usage
As described in the installation guide,
http://docs.openstack.org/developer/trove/dev/manual_install.html
a running OpenStack environment is required to use Trove, including
the following components:
- Compute (Nova)
- Image Service (Glance)
- Identity (Keystone)
- Neutron or Nova-Network
- Cinder, if you want to provision datastores on block-storage volumes
- Swift, if you want to do backup/restore and replication
- AMQP service (RabbitMQ or QPID)
- MySQL (SQLite, PostgreSQL) database for Trove's internal needs
- Certain OpenStack services must be accessible from VMs:
- Swift
OpenStack services must be accessible directly from the environment where
Trove is deployed:
- Nova
- Cinder
- Swift
- Heat
A basic setup with using charms would look like the following:
juju deploy trove
juju deploy mysql
juju deploy rabbitmq-server
juju deploy keystone
juju deploy cinder
juju deploy glance
juju deploy nova-compute
juju deploy nova-cloud-controller
juju deploy neutron
juju deploy neutron-openvswitch
juju deploy neutron-gateway
juju add-relation trove mysql
juju add-relation trove rabbitmq-server
juju add-relation trove keystone
juju add-relation nova-compute rabbitmq-server
juju add-relation nova-compute glance
juju add-relation cinder keystone
juju add-relation cinder mysql
juju add-relation cinder rabbitmq-server
juju add-relation glance keystone
juju add-relation glance mysql
juju add-relation neutron-gateway mysql
juju add-relation neutron-gateway rabbitmq-server
juju add-relation neutron-gateway:amqp rabbitmq-server:amqp
juju add-relation neutron-openvswitch nova-compute
juju add-relation neutron-openvswitch neutron-api
juju add-relation neutron-openvswitch rabbitmq-server
juju add-relation neutron-api mysql
juju add-relation neutron-api keystone
juju add-relation neutron-api rabbitmq-server
juju add-relation nova-cloud-controller keystone
juju add-relation nova-cloud-controller rabbitmq-server
juju add-relation nova-cloud-controller nova-compute
juju add-relation nova-cloud-controller mysql
juju add-relation nova-cloud-controller glance
juju add-relation nova-cloud-controller cinder
juju add-relation nova-cloud-controller neutron-api
This will get the necessary services deployed, however, you will still need
to create images, flavors and data stores for your specific needs.
http://docs.openstack.org/admin-guide/database.html
# Bugs
Please report bugs on [Launchpad](https://bugs.launchpad.net/charm-trove/+filebug).
For general questions please refer to the OpenStack [Charm Guide](http://docs.openstack.org/developer/charm-guide/).

View File

@ -1,94 +0,0 @@
options:
openstack-origin:
default: distro
type: string
description: |
Repository from which to install. May be one of the following:
distro (default), ppa:somecustom/ppa, a deb url sources entry,
or a supported Cloud Archive release pocket.
Supported Cloud Archive sources include:
cloud:<series>-<openstack-release>
cloud:<series>-<openstack-release>/updates
cloud:<series>-<openstack-release>/staging
cloud:<series>-<openstack-release>/proposed
For series=Xenial we support cloud archives for openstack-release:
* Mitaka
* Newton
NOTE: updating this setting to a source that is known to provide
a later version of OpenStack will trigger a software upgrade.
rabbit-user:
default: trove
type: string
description: Username used to access rabbitmq queue
rabbit-vhost:
default: openstack
type: string
description: Rabbitmq vhost
database-user:
default: trove
type: string
description: Username for Trove database access (if enabled)
database:
default: trove
type: string
description: Database name for Trove (if enabled)
debug:
default: False
type: boolean
description: Enable debug logging
verbose:
default: False
type: boolean
description: Enable verbose logging, deprecated in Newton
region:
default: RegionOne
type: string
description: OpenStack Region
keystone-api-version:
default: "2"
type: string
description: none, 2 or 3
trove-volume-support:
default: True
type: boolean
description: A cinder volume will be provisioned for all datastores (if enabled)
trove-datastore-database:
default: mysql
type: string
description: |
One or more database type(s) for Trove datastores, list is comma separated,
options are: mysql, redis, cassandra, mongodb, vertica
trove-database-volume-support:
default: mysql
type: string
description: |
A cinder volume will be provisioned for individual datastores (if enabled)
One or more database type(s) for Trove instances, list is comma separated,
options are: mysql, redis, cassandra, mongodb, vertica
default-neutron-networks:
default:
type: string
description: |
List of IDs for management networks which should be attached to the
instance regardless of what NICs are specified in the create API call.
use-nova-server-config-drive:
default: False
type: boolean
description: |
Nova config drive will be used with cloud-init to inject parameters and
files into the database instances.
trove-network-label-regex:
default: ".*"
type: string
description: Regular expression to match neutron network labels to determine
what IP addresses will be displayed by Trove.
trove-ip-regex:
default:
type: string
description: Regular expression to match individual IP addresses to determine
if it will be displayed by Trove.
trove-black-list-regex:
default:
type: string
description: Regular expression to match individual IP addresses to determine
if it should not be displayed by Trove.

View File

@ -1,16 +0,0 @@
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0
Files: *
Copyright: 2012, Canonical Ltd.
License: Apache-2.0
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.See the LICENSE file in the root directory.

View File

@ -1,6 +0,0 @@
includes: ['layer:openstack-api']
options:
basic:
use_venv: True
include_system_packages: True
repo: https://github.com/openstack/charm-trove.git

View File

@ -1,259 +0,0 @@
# 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.
# The trove handlers class
# bare functions are provided to the reactive handlers to perform the functions
# needed on the class.
from __future__ import absolute_import
import collections
import charmhelpers.contrib.openstack.utils as ch_utils
import charmhelpers.core.unitdata as unitdata
import charmhelpers.core.hookenv as hookenv
import charms_openstack.charm
import charms_openstack.adapters
import charms_openstack.ip as os_ip
TROVE_DIR = '/etc/trove/'
TROVE_CONF = TROVE_DIR + "trove.conf"
TROVE_API_PASTE_CONF = TROVE_DIR + "api-paste.ini"
TROVE_CONDUCTOR = TROVE_DIR + "trove-conductor.conf"
TROVE_GUEST_AGENT = TROVE_DIR + "trove-guestagent.conf"
TROVE_LOGGING_GUEST_AGENT = TROVE_DIR + "trove-logging-guestagent.conf"
TROVE_TASK_MANAGER = TROVE_DIR + "trove-taskmanager.conf"
OPENSTACK_RELEASE_KEY = 'trove-charm.openstack-release-version'
###
# Handler functions for events that are interesting to the Trove charms
# Copied from the Congress example charm
# https://github.com/openstack/charm-guide/blob/master/doc/source/new-charm.rst
def install():
"""Use the singleton from the TroveCharm to install the packages on the
unit
"""
TroveCharm.singleton.install()
def db_sync_done():
"""Use the singleton from the TroveCharm to check if db migration has
been run
@returns: str or None. Str if sync has been done otherwise None
"""
return TroveCharm.singleton.db_sync_done()
def restart_all():
"""Use the singleton from the TroveCharm to restart services on the
unit
"""
TroveCharm.singleton.restart_all()
def db_sync():
"""Use the singleton from the TroveCharm to run db migration
"""
TroveCharm.singleton.db_sync()
def configure_ha_resources(hacluster):
"""Use the singleton from the TroveCharm to run configure_ha_resources
"""
TroveCharm.singleton.configure_ha_resources(hacluster)
def setup_endpoint(keystone):
"""When the keystone interface connects, register this unit in the keystone
catalogue.
:param keystone: instance of KeystoneRequires() class from i/f
"""
charm = TroveCharm.singleton
public_ep = '{}/v1.0/%(tenant_id)s'.format(charm.public_url)
internal_ep = '{}/v1.0/%(tenant_id)s'.format(charm.internal_url)
admin_ep = '{}/v1.0/%(tenant_id)s'.format(charm.admin_url)
keystone.register_endpoints(charm.service_type,
charm.region,
public_ep,
internal_ep,
admin_ep)
def render_configs(interfaces_list):
"""Using a list of interfaces, render the configs and, if they have
changes, restart the services on the unit.
:param interfaces_list: [RelationBase] interfaces from reactive
"""
TroveCharm.singleton.render_with_interfaces(interfaces_list)
def assess_status():
"""Just call the TroveCharm.singleton.assess_status() command to update
status on the unit.
"""
TroveCharm.singleton.assess_status()
def configure_ssl(keystone=None):
"""Use the singleton from the TroveCharm to configure ssl
:param keystone: KeystoneRequires() interface class
"""
TroveCharm.singleton.configure_ssl(keystone)
def update_peers(hacluster):
"""Use the singleton from the TroveCharm to update peers with details
of this unit.
@param hacluster: OpenstackHAPeers() interface class
@returns: None
"""
TroveCharm.singleton.update_peers(hacluster)
class TroveConfigurationAdapter(
charms_openstack.adapters.APIConfigurationAdapter):
def __init__(self, port_map=None):
super(TroveConfigurationAdapter, self).__init__(
service_name='trove',
port_map=port_map)
if self.keystone_api_version not in ['2', '3', 'none']:
raise ValueError(
"Unsupported keystone-api-version ({}). It should be 2 or 3"
.format(self.keystone_api_version))
class TroveAdapters(charms_openstack.adapters.OpenStackAPIRelationAdapters):
def __init__(self, relations):
super(TroveAdapters, self).__init__(
relations,
options_instance=TroveConfigurationAdapter(
port_map=TroveCharm.api_ports))
class TroveCharm(charms_openstack.charm.HAOpenStackCharm):
service_name = name = 'trove'
release = 'mitaka'
packages = ['python-trove', 'python-troveclient', 'trove-common',
'trove-api', 'trove-taskmanager', 'trove-conductor']
services = ['trove-api', 'trove-taskmanager', 'trove-conductor']
adapters_class = TroveAdapters
default_service = 'trove-api'
api_ports = {
'trove-api': {
os_ip.PUBLIC: 8779,
os_ip.ADMIN: 8779,
os_ip.INTERNAL: 8779,
}
}
sync_cmd = ['trove-manage', 'db_sync']
service_type = 'trove'
required_relations = ['shared-db', 'amqp', 'identity-service']
restart_map = {
TROVE_CONF: services,
TROVE_API_PASTE_CONF: services,
TROVE_CONDUCTOR: services,
TROVE_TASK_MANAGER: services,
TROVE_GUEST_AGENT: services,
TROVE_LOGGING_GUEST_AGENT: services
}
ha_resources = ['vips', 'haproxy']
release_pkg = 'trove-common'
package_codenames = {
'trove-common': collections.OrderedDict([
('2', 'mitaka'),
('3', 'newton'),
('4', 'ocata'),
('5', 'pike'),
('6', 'queens'),
('7', 'rocky'),
]),
}
def install(self):
"""Customise the installation, configure the source and then call the
parent install() method to install the packages
"""
self.configure_source()
# and do the actual install
super(TroveCharm, self).install()
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 (self.config['rabbit-user'], self.config['rabbit-vhost'])
def get_database_setup(self):
"""Provide the default database credentials as a list of 3-tuples
returns a structure of:
[
{'database': <database>,
'username': <username>,
'hostname': <hostname of this unit>
'prefix': <the optional prefix for the database>, },
]
:returns [{'database': ...}, ...]: credentials for multiple databases
"""
host = None
try:
host = hookenv.network_get_primary_address('shared-db')
except NotImplementedError:
host = hookenv.unit_get('private-address')
return [
dict(
database=self.config['database'],
username=self.config['database-user'],
hostname=host, )
]
# Determine the charm class by the supported release
@charms_openstack.charm.register_os_release_selector
def select_release():
"""Determine the release based on the python-keystonemiddleware that is
installed.
Note that this function caches the release after the first install so that
it doesn't need to keep going and getting it from the package information.
"""
release_version = unitdata.kv().get(OPENSTACK_RELEASE_KEY, None)
if release_version is None:
release_version = ch_utils.os_release('python-keystonemiddleware')
unitdata.kv().set(OPENSTACK_RELEASE_KEY, release_version)
return release_version

View File

@ -1,26 +0,0 @@
name: trove
summary: Trove provides DBaaS services for OpenStack
maintainer: TransCirrus <support@transcirrus.com>
description: |
Trove is Database as a Service for OpenStack. It's designed to run entirely on OpenStack,
with the goal of allowing users to quickly and easily utilize the features of a relational
or non-relational database without the burden of handling complex administrative tasks.
tags:
- openstack
- database
series:
- xenial
- yakkety
- zesty
subordinate: false
requires:
ha:
interface: hacluster
scope: container
amqp:
interface: rabbitmq
identity-service:
interface: keystone
peers:
cluster:
interface: openstack-ha

View File

@ -1,69 +0,0 @@
# 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.
# this is just for the reactive handlers and calls into the charm.
from __future__ import absolute_import
import charms.reactive as reactive
import charms_openstack.charm as charm
# This charm's library contains all of the handler code associated with trove
import charm.openstack.trove as trove
charm.use_defaults(
'config.changed',
'amqp.connected',
'identity-service.available',
'charm.installed',
'upgrade-charm',
'update-status',
'shared-db.connected',
)
# this is to check if ha is running
@reactive.when('ha.connected')
def cluster_connected(hacluster):
trove.configure_ha_resources(hacluster)
@reactive.when('identity-service.connected')
def setup_endpoint(keystone):
trove.setup_endpoint(keystone)
trove.assess_status()
@reactive.when('shared-db.available')
@reactive.when('identity-service.available')
@reactive.when('amqp.available')
def render_stuff(*args):
# Get the optional hsm relation, if it is available for rendering.
trove.render_configs(args)
reactive.set_state('config.complete')
trove.assess_status()
@reactive.when('config.complete')
@reactive.when_not('db.synced')
def run_db_migration():
trove.db_sync()
trove.restart_all()
reactive.set_state('db.synced')
trove.assess_status()
@reactive.when('cluster.available')
def update_peers(cluster):
"""Inform designate peers about this unit"""
trove.update_peers(cluster)

View File

@ -1,2 +0,0 @@
flake8
pytest

View File

@ -1,116 +0,0 @@
[DEFAULT]
auth_strategy = keystone
log_dir = /var/log/trove
#trove_auth_url = {{ identity_service.service_protocol }}://{{ identity_service.auth_host }}:{{ identity_service.auth_port }}/v{{ identity_service.api_version }}
notifier_queue_hostname = controller
network_driver = trove.network.neutron.NeutronDriver
# Show more verbose log output (sets INFO log level output)
verbose = {{ options.verbose }}
# Show debugging output in logs (sets DEBUG log level output)
debug = {{ options.debug }}
# Address to bind the API server
bind_host = {{ options.service_listen_info.trove_api.ip }}
# Port the bind the API server to
#bind_port = 8779
bind_port = {{ options.service_listen_info.trove_api.port }}
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
{% include "parts/section-rabbitmq-oslo" %}
{% include "parts/section-database" %}
{% include "parts/section-keystone-authtoken" %}
[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
[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
[percona]
#[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

View File

@ -1 +0,0 @@
These are the prototype config files for the Trove service.

View File

@ -1,46 +0,0 @@
[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 http_proxy_to_wsgi 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
[filter:http_proxy_to_wsgi]
use = egg:oslo.middleware#http_proxy_to_wsgi

View File

@ -1,45 +0,0 @@
###############################################################################
# [ WARNING ]
# trove configuration file maintained by Juju
# local changes may be overwritten.
###############################################################################
[DEFAULT]
verbose = {{ options.verbose }}
debug = {{ options.debug }}
{% if identity_service.api_version == '2' %}
trove_auth_url = {{ identity_service.service_protocol }}://{{ identity_service.auth_host }}:{{ identity_service.auth_port }}/v{{ identity_service.api_version }}.0
{% else %}
trove_auth_url = {{ identity_service.service_protocol }}://{{ identity_service.auth_host }}:{{ identity_service.auth_port }}/v{{ identity_service.api_version }}
{% endif %}
# The manager class to use for conductor. (string value)
# conductor_manager = trove.conductor.manager.Manager
taskmanager_manager = trove.taskmanager.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=<None>
# 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
{% include "parts/section-database" %}
{% include "parts/section-rabbitmq-oslo" %}

View File

@ -1,162 +0,0 @@
###############################################################################
# [ WARNING ]
# trove configuration file maintained by Juju
# version on trove unit may be overwritten.
###############################################################################
[DEFAULT]
use_syslog = False
log_file = trove-guestagent.log
log_dir = /var/log/trove/
ignore_users = os_admin
control_exchange = trove
{% if identity_service.api_version == '2' %}
trove_auth_url = {{ identity_service.service_protocol }}://{{ identity_service.auth_host }}:{{ identity_service.auth_port }}/v{{ identity_service.api_version }}.0
{% else %}
trove_auth_url = {{ identity_service.service_protocol }}://{{ identity_service.auth_host }}:{{ identity_service.auth_port }}/v{{ identity_service.api_version }}
{% endif %}
#=========== 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=<None>
# 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
# ========== Configuration options for Swift ==========
# The swift_url can be specified directly or fetched from Keystone catalog.
# To fetch from Keystone, comment out swift_url, and uncomment the others.
# swift_url = http://10.0.0.1:8080/v1/AUTH_
# Region name of this node. Default value is None.
os_region_name = {{ options.region }}
# Service type to use when searching catalog.
# swift_service_type = object-store
# ========== Datastore Manager Configurations ==========
# Datastore manager implementations.
# Format: list of 'datastore-type:datastore.manager.implementation.module'
# datastore_registry_ext = mysql:trove.guestagent.datastore.mysql.manager.Manager, percona:trove.guestagent.datastore.mysql.manager.Manager
{% if options.trove_datastore_database == "mysql" %}
datastore_registry_ext = mysql:trove.guestagent.datastore.mysql.manager.Manager
{% endif %}
# ========== Default Users / DBs Configuration ==========
# Permissions to grant "root" user by default
root_grant = ALL
root_grant_option = True
# root_grant = ALTER ROUTINE, CREATE, ALTER, CREATE ROUTINE, CREATE TEMPORARY TABLES, CREATE VIEW, CREATE USER, DELETE, DROP, EVENT, EXECUTE, INDEX, INSERT, LOCK TABLES, PROCESS, REFERENCES, SELECT, SHOW DATABASES, SHOW VIEW, TRIGGER, UPDATE, USAGE
# root_grant_option = False
# Default password Length for root password
# default_password_length = 36
# ========== Default Storage Options for backup ==========
# Default configuration for storage strategy and storage options
# for backups
# For storage to Swift, use the following as defaults:
# storage_strategy = SwiftStorage
# storage_namespace = trove.common.strategies.storage.swift
# Default config options for storing backups to swift
# backup_swift_container = database_backups
# backup_use_gzip_compression = True
# backup_use_openssl_encryption = True
# backup_aes_cbc_key = "default_aes_cbc_key"
# backup_use_snet = False
# backup_chunk_size = 65536
# backup_segment_max_size = 2147483648
# ========== Sample Logging Configuration ==========
# Show more verbose log output (sets INFO log level output)
verbose = {{ options.verbose }}
# Show debugging output in logs (sets DEBUG log level output)
debug = {{ options.debug }}
# Directory and path for log files
log_dir = /var/log/trove/
log_file = logfile.txt
#log_config_append = /etc/trove/trove-logging-guestagent.conf
[profiler]
# If False fully disable profiling feature.
#enabled = False
# If False doesn't trace SQL requests.
#trace_sqlalchemy = True
{% include "parts/section-rabbitmq-oslo" %}
# ========== Datastore Specific Configuration Options ==========
[mysql]
# For mysql, the following are the defaults for backup, and restore:
# backup_strategy = InnoBackupEx
# backup_namespace = trove.guestagent.strategies.backup.mysql_impl
# restore_namespace = trove.guestagent.strategies.restore.mysql_impl
# Default configuration for mysql replication
# replication_strategy = MysqlBinlogReplication
# replication_namespace = trove.guestagent.strategies.replication.mysql_binlog
# replication_user = slave_user
# replication_password = slave_password
# Users to ignore for user create/list/delete operations
# ignore_users = os_admin
# Databases to ignore for db create/list/delete operations
# ignore_dbs = mysql, information_schema, performance_schema
#[vertica]
# For vertica, following are the defaults needed:
# mount_point = /var/lib/vertica
# readahead_size = 2048
# guestagent_strategy = trove.common.strategies.cluster.experimental.vertica.guestagent.VerticaGuestAgentStrategy
#[redis]
# For redis, the following are the defaults for backup, and restore:
# backup_strategy = RedisBackup
# backup_namespace = trove.guestagent.strategies.backup.experimental.redis_impl
# restore_namespace = trove.guestagent.strategies.restore.experimental.redis_impl
[percona]
backup_namespace = trove.guestagent.strategies.backup.mysql_impl
restore_namespace = trove.guestagent.strategies.restore.mysql_impl
#[couchbase]
#backup_namespace = trove.guestagent.strategies.backup.experimental.couchbase_impl
#restore_namespace = trove.guestagent.strategies.restore.experimental.couchbase_impl
#[cassandra]
#backup_namespace = trove.guestagent.strategies.backup.experimental.cassandra_impl
#restore_namespace = trove.guestagent.strategies.restore.experimental.cassandra_impl
#[db2]
# For db2, the following are the defaults for backup, and restore:
# backup_strategy = DB2Backup
# backup_namespace = trove.guestagent.strategies.backup.experimental.db2_impl
# restore_namespace = trove.guestagent.strategies.restore.experimental.db2_impl
#[couchdb]
#For CouchDB, the following are the defaults for backup and restore:
# backup_strategy = CouchDBBackup
# backup_namespace = trove.guestagent.strategies.backup.experimental.couchdb_impl
# restore_namespace = trove.guestagent.strategies.restore.experimental.couchdb_impl

View File

@ -1,45 +0,0 @@
###############################################################################
# [ WARNING ]
# trove configuration file maintained by Juju
# version on trove unit may be overwritten.
###############################################################################
[loggers]
keys=root
[handlers]
keys=file
[formatters]
keys=minimal,normal,debug
###########
# Loggers #
###########
[logger_root]
level=WARNING
handlers=file
################
# Log Handlers #
################
[handler_file]
class=logging.handlers.RotatingFileHandler
level=WARNING
formatter=normal
args=('/var/log/trove-guestagent.log', 'a', 100 * 1024 * 1024) # log file limit is 100MB
##################
# Log Formatters #
##################
[formatter_minimal]
format=%(message)s
[formatter_normal]
format=(%(name)s): %(asctime)s %(levelname)s %(message)s
[formatter_debug]
format=(%(name)s): %(asctime)s %(levelname)s %(module)s %(funcName)s %(message)s

View File

@ -1,149 +0,0 @@
###############################################################################
# [ WARNING ]
# trove configuration file maintained by Juju
# local changes may be overwritten.
###############################################################################
[DEFAULT]
# Show more verbose log output (sets INFO log level output)
verbose = {{ options.verbose }}
# Show debugging output in logs (sets DEBUG log level output)
debug = {{ options.debug }}
network_driver = trove.network.neutron.NeutronDriver
{% if options.default_neutron_networks %}
default_neutron_networks = {{ options.default_neutron_networks }}
{% else %}
default_neutron_networks =
{% endif %}
update_status_on_fail = True
log_dir = /var/log/trove
{% if identity_service.api_version == '2' %}
trove_auth_url = {{ identity_service.service_protocol }}://{{ identity_service.auth_host }}:{{ identity_service.auth_port }}/v{{ identity_service.api_version }}.0
{% else %}
trove_auth_url = {{ identity_service.service_protocol }}://{{ identity_service.auth_host }}:{{ identity_service.auth_port }}/v{{ identity_service.api_version }}
{% endif %}
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
taskmanager_manager = trove.taskmanager.manager.Manager
# Region name of this node. Used when searching catalog. Default value is None.
os_region_name = {{ options.region }}
# 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 = {{ options.trove_volume_support }}
block_device_mapping = vdb
device_path = /dev/vdb
mount_point = /var/lib/mysql
volume_time_out=30
server_delete_time_out=480
# Nova server boot options
# sets the --config-drive argument when doing a nova boot
# (controls how file injection is handled by nova)
use_nova_server_config_drive = {{ options.use_nova_server_config_drive }}
# ================= Guestagent related ========================
guest_config = /etc/trove/conf.d/trove-guestagent.conf
# Use 'guest_info = /etc/guest_info' for pre-Kilo compatibility
#guest_info = guest_info.conf
# Use 'injected_config_location = /etc/trove' for pre-Kilo compatibility
injected_config_location = /etc/trove/conf.d
cloudinit_location = /etc/trove/cloudinit
{% if 'mysql' in options.trove_database %}
[mysql]
tcp_ports = 3306
{% if 'mysql' in options.trove_database_volume_support %}
volume_support = True
{% else %}
volume_support = False
{% endif %}
device_path = /dev/vdb
{% endif %}
{% if 'redis' in options.trove_database %}
[redis]
# Format (single port or port range): A, B-C
# where C greater than B
tcp_ports = 6379
{% if 'redis' in options.trove_database_volume_support %}
volume_support = True
{% else %}
volume_support = False
{% endif %}
# redis uses local storage
# default device_path = None
{% endif %}
{% if 'cassandra' in options.trove_database %}
[cassandra]
tcp_ports = 7000, 7001, 9042, 9160
{% if 'cassandra' in options.trove_database_volume_support %}
volume_support = True
{% else %}
volume_support = False
{% endif %}
device_path = /dev/vdb
{% endif %}
{% if 'couchbase' in options.trove_database %}
[couchbase]
tcp_ports = 8091, 8092, 4369, 11209-11211, 21100-21199
{% if 'couchbase' in options.trove_database_volume_support %}
volume_support = True
{% else %}
volume_support = False
{% endif %}
device_path = /dev/vdb
{% endif %}
{% if 'mongodb' in options.trove_database %}
[mongodb]
{% if 'mongodb' in options.trove_database_volume_support %}
volume_support = True
{% else %}
volume_support = False
{% endif %}
device_path = /dev/vdb
{% endif %}
{% if 'vertica' in options.trove_database %}
[vertica]
tcp_ports = 5433, 5434, 22, 5444, 5450, 4803
udp_ports = 5433, 4803, 4804, 6453
{% if 'vertica' in options.trove_database_volume_support %}
volume_support = True
{% else %}
volume_support = False
{% endif %}
device_path = /dev/vdb
mount_point = /var/lib/vertica
taskmanager_strategy = trove.common.strategies.cluster.experimental.vertica.taskmanager.VerticaTaskManagerStrategy
{% endif %}
{% include "parts/section-rabbitmq-oslo" %}
{% include "parts/section-database" %}

View File

@ -1,176 +0,0 @@
###############################################################################
# [ WARNING ]
# trove configuration file maintained by Juju
# local changes may be overwritten.
###############################################################################
[DEFAULT]
auth_strategy = keystone
log_dir = /var/log/trove
{% if identity_service.api_version == '2' %}
trove_auth_url = {{ identity_service.service_protocol }}://{{ identity_service.auth_host }}:{{ identity_service.auth_port }}/v{{ identity_service.api_version }}.0
{% else %}
trove_auth_url = {{ identity_service.service_protocol }}://{{ identity_service.auth_host }}:{{ identity_service.auth_port }}/v{{ identity_service.api_version }}
{% endif %}
notifier_queue_hostname = controller
network_driver = trove.network.neutron.NeutronDriver
{% if options.default_neutron_networks %}
default_neutron_networks = {{ options.default_neutron_networks }}
{% else %}
default_neutron_networks =
{% endif %}
# Show more verbose log output (sets INFO log level output)
verbose = {{ options.verbose }}
# Show debugging output in logs (sets DEBUG log level output)
debug = {{ options.debug }}
# Address to bind the API server
bind_host = {{ options.service_listen_info.trove_api.ip }}
# Port the bind the API server to
#bind_port = 8779
bind_port = {{ options.service_listen_info.trove_api.port }}
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 = {{ options.region }}
# 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 option for showing the IP address that nova doles out
# For nova-network, set this to the appropriate network label defined in nova
# For neutron, set this to .* since users can specify custom network labels
# You can also optionally specify regex'es to match the actual IP addresses
# ip_regex (white-list) is applied before black_list_regex in the filter chain
#network_label_regex = ^private$
#with neutron enabled
network_label_regex = {{ options.trove_network_label_regex }}
#ip_regex = ^(15.|123.)
{% if options.trove_ip_regex %}
ip_regex = {{ options.trove_ip_regex }}
{% endif %}
#black_list_regex = ^10.0.0.
{% if options.trove_black_list_regex %}
black_list_regex = {{ options.trove_black_list_regex }}
{% endif %}
# Config options for enabling volume service
trove_volume_support = {{ options.trove_volume_support }}
#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
{% include "parts/section-rabbitmq-oslo" %}
{% include "parts/section-database" %}
{% include "parts/section-keystone-authtoken" %}
{% if 'mysql' in options.trove_database %}
[mysql]
root_on_create = False
# Format (single port or port range): A, B-C
# where C greater than B
tcp_ports = 3306
{% if 'mysql' in options.trove_database_volume_support %}
volume_support = True
{% else %}
volume_support = False
{% endif %}
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
{% endif %}
[percona]
{% if 'redis' in options.trove_database %}
[redis]
tcp_ports = 6379
#redis uses local storage
# default device_path = None
{% if 'redis' in options.trove_database_volume_support %}
volume_support = True
{% else %}
volume_support = False
{% endif %}
{% endif %}
{% if 'cassandra' in options.trove_database %}
[cassandra]
tcp_ports = 7000, 7001, 9042, 9160
{% if 'cassandra' in options.trove_database_volume_support %}
volume_support = True
{% else %}
volume_support = False
{% endif %}
device_path = /dev/vdb
{% endif %}
{% if 'couchbase' in options.trove_database %}
[couchbase]
tcp_ports = 8091, 8092, 4369, 11209-11211, 21100-21199
{% if 'couchbase' in options.trove_database_volume_support %}
volume_support = True
{% else %}
volume_support = False
{% endif %}
device_path = /dev/vdb
{% endif %}
{% if 'mongodb' in options.trove_database %}
[mongodb]
tcp_ports = 2500, 27017
{% if 'mongodb' in options.trove_database_volume_support %}
volume_support = True
{% else %}
volume_support = False
{% endif %}
device_path = /dev/vdb
num_config_servers_per_cluster = 1
num_query_routers_per_cluster = 1
{% endif %}
{% if 'vertica' in options.trove_database %}
[vertica]
tcp_ports = 5433, 5434, 22, 5444, 5450, 4803
udp_ports = 5433, 4803, 4804, 6453
{% if 'vertica' in options.trove_database_volume_support %}
volume_support = True
{% else %}
volume_support = False
{% endif %}
device_path = /dev/vdb
cluster_support = True
cluster_member_count = 3
api_strategy = trove.common.strategies.cluster.experimental.vertica.api.VerticaAPIStrategy
{% endif %}

View File

@ -1 +0,0 @@
These are the prototype config files for the Trove service.

View File

@ -1,44 +0,0 @@
###############################################################################
# [ WARNING ]
# trove configuration file maintained by Juju
# local changes may be overwritten.
###############################################################################
[DEFAULT]
debug = {{ options.debug }}
{% if identity_service.api_version == '2' %}
trove_auth_url = {{ identity_service.service_protocol }}://{{ identity_service.auth_host }}:{{ identity_service.auth_port }}/v{{ identity_service.api_version }}.0
{% else %}
trove_auth_url = {{ identity_service.service_protocol }}://{{ identity_service.auth_host }}:{{ identity_service.auth_port }}/v{{ identity_service.api_version }}
{% endif %}
# The manager class to use for conductor. (string value)
# conductor_manager = trove.conductor.manager.Manager
taskmanager_manager = trove.taskmanager.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=<None>
# 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
{% include "parts/section-database" %}
{% include "parts/section-rabbitmq-oslo" %}

View File

@ -1,159 +0,0 @@
###############################################################################
# [ WARNING ]
# trove configuration file maintained by Juju
# version on trove unit may be overwritten.
###############################################################################
[DEFAULT]
use_syslog = False
log_file = trove-guestagent.log
log_dir = /var/log/trove/
ignore_users = os_admin
control_exchange = trove
{% if identity_service.api_version == '2' %}
trove_auth_url = {{ identity_service.service_protocol }}://{{ identity_service.auth_host }}:{{ identity_service.auth_port }}/v{{ identity_service.api_version }}.0
{% else %}
trove_auth_url = {{ identity_service.service_protocol }}://{{ identity_service.auth_host }}:{{ identity_service.auth_port }}/v{{ identity_service.api_version }}
{% endif %}
#=========== 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=<None>
# 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
# ========== Configuration options for Swift ==========
# The swift_url can be specified directly or fetched from Keystone catalog.
# To fetch from Keystone, comment out swift_url, and uncomment the others.
# swift_url = http://10.0.0.1:8080/v1/AUTH_
# Region name of this node. Default value is None.
os_region_name = {{ options.region }}
# Service type to use when searching catalog.
# swift_service_type = object-store
# ========== Datastore Manager Configurations ==========
# Datastore manager implementations.
# Format: list of 'datastore-type:datastore.manager.implementation.module'
# datastore_registry_ext = mysql:trove.guestagent.datastore.mysql.manager.Manager, percona:trove.guestagent.datastore.mysql.manager.Manager
{% if options.trove_datastore_database == "mysql" %}
datastore_registry_ext = mysql:trove.guestagent.datastore.mysql.manager.Manager
{% endif %}
# ========== Default Users / DBs Configuration ==========
# Permissions to grant "root" user by default
root_grant = ALL
root_grant_option = True
# root_grant = ALTER ROUTINE, CREATE, ALTER, CREATE ROUTINE, CREATE TEMPORARY TABLES, CREATE VIEW, CREATE USER, DELETE, DROP, EVENT, EXECUTE, INDEX, INSERT, LOCK TABLES, PROCESS, REFERENCES, SELECT, SHOW DATABASES, SHOW VIEW, TRIGGER, UPDATE, USAGE
# root_grant_option = False
# Default password Length for root password
# default_password_length = 36
# ========== Default Storage Options for backup ==========
# Default configuration for storage strategy and storage options
# for backups
# For storage to Swift, use the following as defaults:
# storage_strategy = SwiftStorage
# storage_namespace = trove.common.strategies.storage.swift
# Default config options for storing backups to swift
# backup_swift_container = database_backups
# backup_use_gzip_compression = True
# backup_use_openssl_encryption = True
# backup_aes_cbc_key = "default_aes_cbc_key"
# backup_use_snet = False
# backup_chunk_size = 65536
# backup_segment_max_size = 2147483648
# ========== Sample Logging Configuration ==========
# Show debugging output in logs (sets DEBUG log level output)
debug = {{ options.debug }}
# Directory and path for log files
log_dir = /var/log/trove/
log_file = logfile.txt
#log_config_append = /etc/trove/trove-logging-guestagent.conf
[profiler]
# If False fully disable profiling feature.
#enabled = False
# If False doesn't trace SQL requests.
#trace_sqlalchemy = True
{% include "parts/section-rabbitmq-oslo" %}
# ========== Datastore Specific Configuration Options ==========
[mysql]
# For mysql, the following are the defaults for backup, and restore:
# backup_strategy = InnoBackupEx
# backup_namespace = trove.guestagent.strategies.backup.mysql_impl
# restore_namespace = trove.guestagent.strategies.restore.mysql_impl
# Default configuration for mysql replication
# replication_strategy = MysqlBinlogReplication
# replication_namespace = trove.guestagent.strategies.replication.mysql_binlog
# replication_user = slave_user
# replication_password = slave_password
# Users to ignore for user create/list/delete operations
# ignore_users = os_admin
# Databases to ignore for db create/list/delete operations
# ignore_dbs = mysql, information_schema, performance_schema
#[vertica]
# For vertica, following are the defaults needed:
# mount_point = /var/lib/vertica
# readahead_size = 2048
# guestagent_strategy = trove.common.strategies.cluster.experimental.vertica.guestagent.VerticaGuestAgentStrategy
#[redis]
# For redis, the following are the defaults for backup, and restore:
# backup_strategy = RedisBackup
# backup_namespace = trove.guestagent.strategies.backup.experimental.redis_impl
# restore_namespace = trove.guestagent.strategies.restore.experimental.redis_impl
[percona]
backup_namespace = trove.guestagent.strategies.backup.mysql_impl
restore_namespace = trove.guestagent.strategies.restore.mysql_impl
#[couchbase]
#backup_namespace = trove.guestagent.strategies.backup.experimental.couchbase_impl
#restore_namespace = trove.guestagent.strategies.restore.experimental.couchbase_impl
#[cassandra]
#backup_namespace = trove.guestagent.strategies.backup.experimental.cassandra_impl
#restore_namespace = trove.guestagent.strategies.restore.experimental.cassandra_impl
#[db2]
# For db2, the following are the defaults for backup, and restore:
# backup_strategy = DB2Backup
# backup_namespace = trove.guestagent.strategies.backup.experimental.db2_impl
# restore_namespace = trove.guestagent.strategies.restore.experimental.db2_impl
#[couchdb]
#For CouchDB, the following are the defaults for backup and restore:
# backup_strategy = CouchDBBackup
# backup_namespace = trove.guestagent.strategies.backup.experimental.couchdb_impl
# restore_namespace = trove.guestagent.strategies.restore.experimental.couchdb_impl

View File

@ -1,45 +0,0 @@
###############################################################################
# [ WARNING ]
# trove configuration file maintained by Juju
# version on trove unit may be overwritten.
###############################################################################
[loggers]
keys=root
[handlers]
keys=file
[formatters]
keys=minimal,normal,debug
###########
# Loggers #
###########
[logger_root]
level=WARNING
handlers=file
################
# Log Handlers #
################
[handler_file]
class=logging.handlers.RotatingFileHandler
level=WARNING
formatter=normal
args=('/var/log/trove-guestagent.log', 'a', 100 * 1024 * 1024) # log file limit is 100MB
##################
# Log Formatters #
##################
[formatter_minimal]
format=%(message)s
[formatter_normal]
format=(%(name)s): %(asctime)s %(levelname)s %(message)s
[formatter_debug]
format=(%(name)s): %(asctime)s %(levelname)s %(module)s %(funcName)s %(message)s

View File

@ -1,146 +0,0 @@
###############################################################################
# [ WARNING ]
# trove configuration file maintained by Juju
# local changes may be overwritten.
###############################################################################
[DEFAULT]
# Show debugging output in logs (sets DEBUG log level output)
debug = {{ options.debug }}
network_driver = trove.network.neutron.NeutronDriver
{% if options.default_neutron_networks %}
default_neutron_networks = {{ options.default_neutron_networks }}
{% else %}
default_neutron_networks =
{% endif %}
update_status_on_fail = True
log_dir = /var/log/trove
{% if identity_service.api_version == '2' %}
trove_auth_url = {{ identity_service.service_protocol }}://{{ identity_service.auth_host }}:{{ identity_service.auth_port }}/v{{ identity_service.api_version }}.0
{% else %}
trove_auth_url = {{ identity_service.service_protocol }}://{{ identity_service.auth_host }}:{{ identity_service.auth_port }}/v{{ identity_service.api_version }}
{% endif %}
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
taskmanager_manager = trove.taskmanager.manager.Manager
# Region name of this node. Used when searching catalog. Default value is None.
os_region_name = {{ options.region }}
# 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 = {{ options.trove_volume_support }}
block_device_mapping = vdb
device_path = /dev/vdb
mount_point = /var/lib/mysql
volume_time_out=30
server_delete_time_out=480
# Nova server boot options
# sets the --config-drive argument when doing a nova boot
# (controls how file injection is handled by nova)
use_nova_server_config_drive = {{ options.use_nova_server_config_drive }}
# ================= Guestagent related ========================
guest_config = /etc/trove/conf.d/trove-guestagent.conf
# Use 'guest_info = /etc/guest_info' for pre-Kilo compatibility
#guest_info = guest_info.conf
# Use 'injected_config_location = /etc/trove' for pre-Kilo compatibility
injected_config_location = /etc/trove/conf.d
cloudinit_location = /etc/trove/cloudinit
{% if 'mysql' in options.trove_database %}
[mysql]
tcp_ports = 3306
{% if 'mysql' in options.trove_database_volume_support %}
volume_support = True
{% else %}
volume_support = False
{% endif %}
device_path = /dev/vdb
{% endif %}
{% if 'redis' in options.trove_database %}
[redis]
# Format (single port or port range): A, B-C
# where C greater than B
tcp_ports = 6379
{% if 'redis' in options.trove_database_volume_support %}
volume_support = True
{% else %}
volume_support = False
{% endif %}
# redis uses local storage
# default device_path = None
{% endif %}
{% if 'cassandra' in options.trove_database %}
[cassandra]
tcp_ports = 7000, 7001, 9042, 9160
{% if 'cassandra' in options.trove_database_volume_support %}
volume_support = True
{% else %}
volume_support = False
{% endif %}
device_path = /dev/vdb
{% endif %}
{% if 'couchbase' in options.trove_database %}
[couchbase]
tcp_ports = 8091, 8092, 4369, 11209-11211, 21100-21199
{% if 'couchbase' in options.trove_database_volume_support %}
volume_support = True
{% else %}
volume_support = False
{% endif %}
device_path = /dev/vdb
{% endif %}
{% if 'mongodb' in options.trove_database %}
[mongodb]
{% if 'mongodb' in options.trove_database_volume_support %}
volume_support = True
{% else %}
volume_support = False
{% endif %}
device_path = /dev/vdb
{% endif %}
{% if 'vertica' in options.trove_database %}
[vertica]
tcp_ports = 5433, 5434, 22, 5444, 5450, 4803
udp_ports = 5433, 4803, 4804, 6453
{% if 'vertica' in options.trove_database_volume_support %}
volume_support = True
{% else %}
volume_support = False
{% endif %}
device_path = /dev/vdb
mount_point = /var/lib/vertica
taskmanager_strategy = trove.common.strategies.cluster.experimental.vertica.taskmanager.VerticaTaskManagerStrategy
{% endif %}
{% include "parts/section-rabbitmq-oslo" %}
{% include "parts/section-database" %}

View File

@ -1,173 +0,0 @@
###############################################################################
# [ WARNING ]
# trove configuration file maintained by Juju
# local changes may be overwritten.
###############################################################################
[DEFAULT]
auth_strategy = keystone
log_dir = /var/log/trove
{% if identity_service.api_version == '2' %}
trove_auth_url = {{ identity_service.service_protocol }}://{{ identity_service.auth_host }}:{{ identity_service.auth_port }}/v{{ identity_service.api_version }}.0
{% else %}
trove_auth_url = {{ identity_service.service_protocol }}://{{ identity_service.auth_host }}:{{ identity_service.auth_port }}/v{{ identity_service.api_version }}
{% endif %}
notifier_queue_hostname = controller
network_driver = trove.network.neutron.NeutronDriver
{% if options.default_neutron_networks %}
default_neutron_networks = {{ options.default_neutron_networks }}
{% else %}
default_neutron_networks =
{% endif %}
# Show debugging output in logs (sets DEBUG log level output)
debug = {{ options.debug }}
# Address to bind the API server
bind_host = {{ options.service_listen_info.trove_api.ip }}
# Port the bind the API server to
#bind_port = 8779
bind_port = {{ options.service_listen_info.trove_api.port }}
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 = {{ options.region }}
# 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 option for showing the IP address that nova doles out
# For nova-network, set this to the appropriate network label defined in nova
# For neutron, set this to .* since users can specify custom network labels
# You can also optionally specify regex'es to match the actual IP addresses
# ip_regex (white-list) is applied before black_list_regex in the filter chain
#network_label_regex = ^private$
#with neutron enabled
network_label_regex = {{ options.trove_network_label_regex }}
#ip_regex = ^(15.|123.)
{% if options.trove_ip_regex %}
ip_regex = {{ options.trove_ip_regex }}
{% endif %}
#black_list_regex = ^10.0.0.
{% if options.trove_black_list_regex %}
black_list_regex = {{ options.trove_black_list_regex }}
{% endif %}
# Config options for enabling volume service
trove_volume_support = {{ options.trove_volume_support }}
#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
{% include "parts/section-rabbitmq-oslo" %}
{% include "parts/section-database" %}
{% include "parts/section-keystone-authtoken" %}
{% if 'mysql' in options.trove_database %}
[mysql]
root_on_create = False
# Format (single port or port range): A, B-C
# where C greater than B
tcp_ports = 3306
{% if 'mysql' in options.trove_database_volume_support %}
volume_support = True
{% else %}
volume_support = False
{% endif %}
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
{% endif %}
[percona]
{% if 'redis' in options.trove_database %}
[redis]
tcp_ports = 6379
#redis uses local storage
# default device_path = None
{% if 'redis' in options.trove_database_volume_support %}
volume_support = True
{% else %}
volume_support = False
{% endif %}
{% endif %}
{% if 'cassandra' in options.trove_database %}
[cassandra]
tcp_ports = 7000, 7001, 9042, 9160
{% if 'cassandra' in options.trove_database_volume_support %}
volume_support = True
{% else %}
volume_support = False
{% endif %}
device_path = /dev/vdb
{% endif %}
{% if 'couchbase' in options.trove_database %}
[couchbase]
tcp_ports = 8091, 8092, 4369, 11209-11211, 21100-21199
{% if 'couchbase' in options.trove_database_volume_support %}
volume_support = True
{% else %}
volume_support = False
{% endif %}
device_path = /dev/vdb
{% endif %}
{% if 'mongodb' in options.trove_database %}
[mongodb]
tcp_ports = 2500, 27017
{% if 'mongodb' in options.trove_database_volume_support %}
volume_support = True
{% else %}
volume_support = False
{% endif %}
device_path = /dev/vdb
num_config_servers_per_cluster = 1
num_query_routers_per_cluster = 1
{% endif %}
{% if 'vertica' in options.trove_database %}
[vertica]
tcp_ports = 5433, 5434, 22, 5444, 5450, 4803
udp_ports = 5433, 4803, 4804, 6453
{% if 'vertica' in options.trove_database_volume_support %}
volume_support = True
{% else %}
volume_support = False
{% endif %}
device_path = /dev/vdb
cluster_support = True
cluster_member_count = 3
api_strategy = trove.common.strategies.cluster.experimental.vertica.api.VerticaAPIStrategy
{% endif %}

View File

@ -1,20 +0,0 @@
# charm-proof
charm-tools>=2.0.0
# amulet deployment helpers
git+https://github.com/juju/charm-helpers
# BEGIN: Amulet OpenStack Charm Helper Requirements
# Liberty client lower constraints
amulet>=1.14.3,<2.0
bundletester>=0.6.1,<1.0
python-keystoneclient>=1.7.1,<2.0
python-troveclient>=1.5,<=2.7.0
python-cinderclient>=1.4.0,<2.0
python-glanceclient>=1.1.0,<2.0
python-heatclient>=0.8.0,<1.0
python-neutronclient>=3.1.0,<4.0
python-novaclient>=2.30.1,<3.0
python-openstackclient>=1.7.0,<2.0
python-swiftclient>=2.6.0,<3.0
pika>=0.10.0,<1.0
distro-info
# END: Amulet OpenStack Charm Helper Requirements

View File

@ -1,9 +0,0 @@
# Overview
This directory provides Amulet tests to verify basic deployment functionality
from the perspective of this charm, its requirements and its features, as
exercised in a subset of the full OpenStack deployment test bundle topology.
For full details on functional testing of OpenStack charms please refer to
the [functional testing](http://docs.openstack.org/developer/charm-guide/testing.html#functional-testing)
section of the OpenStack Charm Guide.

View File

@ -1,337 +0,0 @@
# 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 amulet
import json
import subprocess
import time
import troveclient.client as trove_client
import charmhelpers.contrib.openstack.amulet.deployment as amulet_deployment
import charmhelpers.contrib.openstack.amulet.utils as os_amulet_utils
# Use DEBUG to turn on debug logging
u = os_amulet_utils.OpenStackAmuletUtils(os_amulet_utils.DEBUG)
class TroveBasicDeployment(amulet_deployment.OpenStackAmuletDeployment):
"""Amulet tests on a basic trove deployment."""
def __init__(self, series, openstack=None, source=None, stable=False):
"""Deploy the entire test environment."""
super(TroveBasicDeployment, self).__init__(series, openstack,
source, stable)
self._add_services()
self._add_relations()
self._configure_services()
self._deploy()
u.log.info('Waiting on extended status checks...')
exclude_services = ['mysql', 'mongodb']
self._auto_wait_for_status(exclude_services=exclude_services)
self._initialize_tests()
def _add_services(self):
"""Add services
Add the services that we're testing, where trove is local,
and the rest of the service are from lp branches that are
compatible with the local charm (e.g. stable or next).
"""
this_service = {'name': 'trove'}
other_services = [{'name': 'mysql'},
{'name': 'rabbitmq-server'},
{'name': 'keystone'},]
super(TroveBasicDeployment, self)._add_services(this_service,
other_services)
def _add_relations(self):
"""Add all of the relations for the services."""
relations = {
'trove:shared-db': 'mysql:shared-db',
'trove:amqp': 'rabbitmq-server:amqp',
'trove:identity-service': 'keystone:identity-service',
'keystone:shared-db': 'mysql:shared-db',
}
super(TroveBasicDeployment, self)._add_relations(relations)
def _configure_services(self):
"""Configure all of the services."""
keystone_config = {'admin-password': 'openstack',
'admin-token': 'ubuntutesting'}
configs = {'keystone': keystone_config}
super(TroveBasicDeployment, self)._configure_services(configs)
def _get_token(self):
return self.keystone.service_catalog.catalog['token']['id']
def _initialize_tests(self):
"""Perform final initialization before tests get run."""
# Access the sentries for inspecting service units
self.trove_sentry = self.d.sentry['trove'][0]
self.mysql_sentry = self.d.sentry['mysql'][0]
self.keystone_sentry = self.d.sentry['keystone'][0]
self.rabbitmq_sentry = self.d.sentry['rabbitmq-server'][0]
u.log.debug('openstack release val: {}'.format(
self._get_openstack_release()))
u.log.debug('openstack release str: {}'.format(
self._get_openstack_release_string()))
self.trove_svcs = ['trove-api', 'trove-taskmanager', 'trove-conductor',]
# Authenticate admin with keystone endpoint
self.keystone = u.authenticate_keystone_admin(self.keystone_sentry,
user='admin',
password='openstack',
tenant='admin')
# Authenticate admin with trove endpoint
trove_ep = self.keystone.service_catalog.url_for(
service_type='database',
interface='publicURL')
keystone_ep = self.keystone.service_catalog.url_for(
service_type='identity',
interface='publicURL')
self.trove = trove_client.Client(
version='1.0',
auth_url=keystone_ep,
username="admin",
password="openstack",
tenant_name="admin",
endpoint=trove_ep)
def check_and_wait(self, check_command, interval=2, max_wait=200,
desc=None):
waited = 0
while not check_command() or waited > max_wait:
if desc:
u.log.debug(desc)
time.sleep(interval)
waited = waited + interval
if waited > max_wait:
raise Exception('cmd failed {}'.format(check_command))
def _run_action(self, unit_id, action, *args):
command = ["juju", "action", "do", "--format=json", unit_id, action]
command.extend(args)
print("Running command: %s\n" % " ".join(command))
output = subprocess.check_output(command)
output_json = output.decode(encoding="UTF-8")
data = json.loads(output_json)
action_id = data[u'Action queued with id']
return action_id
def _wait_on_action(self, action_id):
command = ["juju", "action", "fetch", "--format=json", action_id]
while True:
try:
output = subprocess.check_output(command)
except Exception as e:
print(e)
return False
output_json = output.decode(encoding="UTF-8")
data = json.loads(output_json)
if data[u"status"] == "completed":
return True
elif data[u"status"] == "failed":
return False
time.sleep(2)
def test_services(self):
"""Verify the expected services are running on the corresponding
service units."""
u.log.debug('Checking system services on units...')
service_names = {
self.trove_sentry: self.trove_svcs,
}
ret = u.validate_services_by_name(service_names)
if ret:
amulet.raise_status(amulet.FAIL, msg=ret)
u.log.debug('OK')
def test_service_catalog(self):
"""Verify that the service catalog endpoint data is valid."""
u.log.debug('Checking keystone service catalog data...')
endpoint_check = {
'adminURL': u.valid_url,
'id': u.not_null,
'region': 'RegionOne',
'publicURL': u.valid_url,
'internalURL': u.valid_url
}
expected = {
'database': [endpoint_check],
}
actual = self.keystone.service_catalog.get_endpoints()
ret = u.validate_svc_catalog_endpoint_data(expected, actual)
if ret:
amulet.raise_status(amulet.FAIL, msg=ret)
u.log.debug('OK')
def test_trove_api_endpoint(self):
"""Verify the trove api endpoint data."""
u.log.debug('Checking trove api endpoint data...')
endpoints = self.keystone.endpoints.list()
u.log.debug(endpoints)
admin_port = internal_port = public_port = '8779'
expected = {'id': u.not_null,
'region': 'RegionOne',
'adminurl': u.valid_url,
'internalurl': u.valid_url,
'publicurl': u.valid_url,
'service_id': u.not_null}
ret = u.validate_endpoint_data(endpoints, admin_port, internal_port,
public_port, expected)
if ret:
message = 'Trove endpoint: {}'.format(ret)
amulet.raise_status(amulet.FAIL, msg=message)
u.log.debug('OK')
def test_trove_identity_relation(self):
"""Verify the trove to keystone identity-service relation data"""
u.log.debug('Checking trove to keystone identity-service '
'relation data...')
unit = self.trove_sentry
relation = ['identity-service', 'keystone:identity-service']
trove_ip = unit.relation(
'identity-service',
'keystone:identity-service')['private-address']
trove_endpoint = "http://{}:8779/v1.0/%(tenant_id)s".format(trove_ip)
expected = {
'admin_url': trove_endpoint,
'internal_url': trove_endpoint,
'private-address': trove_ip,
'public_url': trove_endpoint,
'region': 'RegionOne',
'service': 'trove',
}
ret = u.validate_relation_data(unit, relation, expected)
if ret:
message = u.relation_error('trove identity-service', ret)
amulet.raise_status(amulet.FAIL, msg=message)
u.log.debug('OK')
def test_keystone_trove_identity_relation(self):
"""Verify the keystone to trove identity-service relation data"""
u.log.debug('Checking keystone:trove identity relation data...')
unit = self.keystone_sentry
relation = ['identity-service', 'trove:identity-service']
id_relation = unit.relation('identity-service',
'trove:identity-service')
id_ip = id_relation['private-address']
expected = {
'admin_token': 'ubuntutesting',
'auth_host': id_ip,
'auth_port': "35357",
'auth_protocol': 'http',
'private-address': id_ip,
'service_host': id_ip,
'service_password': u.not_null,
'service_port': "5000",
'service_protocol': 'http',
'service_tenant': 'services',
'service_tenant_id': u.not_null,
'service_username': 'trove',
}
ret = u.validate_relation_data(unit, relation, expected)
if ret:
message = u.relation_error('keystone identity-service', ret)
amulet.raise_status(amulet.FAIL, msg=message)
u.log.debug('OK')
def test_trove_amqp_relation(self):
"""Verify the trove to rabbitmq-server amqp relation data"""
u.log.debug('Checking trove:rabbitmq amqp relation data...')
unit = self.trove_sentry
relation = ['amqp', 'rabbitmq-server:amqp']
expected = {
'username': 'trove',
'private-address': u.valid_ip,
'vhost': 'openstack'
}
ret = u.validate_relation_data(unit, relation, expected)
if ret:
message = u.relation_error('trove amqp', ret)
amulet.raise_status(amulet.FAIL, msg=message)
u.log.debug('OK')
def test_amqp_trove_relation(self):
"""Verify the rabbitmq-server to trove amqp relation data"""
u.log.debug('Checking rabbitmq:trove amqp relation data...')
unit = self.rabbitmq_sentry
relation = ['amqp', 'trove:amqp']
expected = {
'hostname': u.valid_ip,
'private-address': u.valid_ip,
'password': u.not_null,
}
ret = u.validate_relation_data(unit, relation, expected)
if ret:
message = u.relation_error('rabbitmq amqp', ret)
amulet.raise_status(amulet.FAIL, msg=message)
u.log.debug('OK')
def test_restart_on_config_change(self):
"""Verify that the specified services are restarted when the config
is changed.
"""
sentry = self.trove_sentry
juju_service = 'trove'
# Expected default and alternate values
set_default = {'debug': 'False'}
set_alternate = {'debug': 'True'}
# Services which are expected to restart upon config change,
# and corresponding config files affected by the change
conf_file = '/etc/trove/trove.conf'
services = {svc: conf_file for svc in self.trove_svcs}
# Make config change, check for service restarts
u.log.debug('Making config change on {}...'.format(juju_service))
mtime = u.get_sentry_time(sentry)
self.d.configure(juju_service, set_alternate)
sleep_time = 50
for s, conf_file in services.iteritems():
u.log.debug("Checking that service restarted: {}".format(s))
if not u.validate_service_config_changed(sentry, mtime, s,
conf_file,
retry_count=4,
retry_sleep_time=20,
sleep_time=sleep_time):
self.d.configure(juju_service, set_default)
msg = "service {} didn't restart after config change".format(s)
amulet.raise_status(amulet.FAIL, msg=msg)
sleep_time = 0
self.d.configure(juju_service, set_default)
u.log.debug('OK')

View File

@ -1,24 +0,0 @@
#!/usr/bin/env python
# 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.
"""Amulet tests on a basic Trove deployment on trusty-mitaka."""
from basic_deployment import TroveBasicDeployment
if __name__ == '__main__':
deployment = TroveBasicDeployment(series='xenial')
deployment.run_tests()

View File

@ -1,17 +0,0 @@
# Bootstrap the model if necessary.
bootstrap: True
# Re-use bootstrap node instead of destroying/re-bootstrapping.
reset: True
# Use tox/requirements to drive the venv instead of bundletester's venv feature.
virtualenv: False
# Leave makefile empty, otherwise unit/lint tests will rerun ahead of amulet.
makefile: []
# Do not specify juju PPA sources. Juju is presumed to be pre-installed
# and configured in all test runner environments.
#sources:
# Do not specify or rely on system packages.
#packages:
# Do not specify python packages here. Use test-requirements.txt
# and tox instead. ie. The venv is constructed before bundletester
# is invoked.
#python-packages:

View File

@ -1,54 +0,0 @@
[tox]
envlist = pep8
skipsdist = True
[testenv]
envdir = .tox/py27
setenv = VIRTUAL_ENV={envdir}
PYTHONHASHSEED=0
AMULET_SETUP_TIMEOUT=2700
passenv = HOME TERM AMULET_HTTP_PROXY AMULET_OS_VIP
deps = -r{toxinidir}/test-requirements.txt
install_command =
pip install --allow-unverified python-apt {opts} {packages}
[testenv:pep8]
basepython = python2.7
commands = charm-proof
[testenv:func27-noop]
# DRY RUN - For Debug
basepython = python2.7
commands =
bundletester -vl DEBUG -r json -o func-results.json --test-pattern "gate-*" -n --no-destroy
[testenv:func27]
# Charm Functional Test
# Run all gate tests which are +x (expected to always pass)
basepython = python2.7
commands =
bundletester -vl DEBUG -r json -o func-results.json --test-pattern "gate-*" --no-destroy
[testenv:func27-smoke]
# Charm Functional Test
# Run a specific test as an Amulet smoke test (expected to always pass)
basepython = python2.7
commands =
bundletester -vl DEBUG -r json -o func-results.json gate-basic-xenial-mitaka --no-destroy
[testenv:func27-dfs]
# Charm Functional Test
# Run all deploy-from-source tests which are +x (may not always pass!)
basepython = python2.7
commands =
bundletester -vl DEBUG -r json -o func-results.json --test-pattern "dfs-*" --no-destroy
[testenv:func27-dev]
# Charm Functional Test
# Run all development test targets which are +x (may not always pass!)
basepython = python2.7
commands =
bundletester -vl DEBUG -r json -o func-results.json --test-pattern "dev-*" --no-destroy
[testenv:venv]
commands = {posargs}

View File

@ -1,7 +0,0 @@
# Unit test requirements
flake8>=2.2.4,<=2.4.1
os-testr>=0.4.1
charms.reactive
mock>=1.2
coverage>=3.6
git+https://github.com/openstack/charms.openstack#egg=charms.openstack

48
tox.ini
View File

@ -1,48 +0,0 @@
[tox]
skipsdist = True
envlist = pep8,py34,py35
skip_missing_interpreters = True
[testenv]
basepython = python2.7
setenv = VIRTUAL_ENV={envdir}
PYTHONHASHSEED=0
TERM=linux
INTERFACE_PATH={toxinidir}/interfaces
LAYER_PATH={toxinidir}/layers
JUJU_REPOSITORY={toxinidir}/build
passenv = http_proxy https_proxy
install_command =
pip install {opts} {packages}
deps =
-r{toxinidir}/requirements.txt
[testenv:build]
commands =
charm-build --log-level DEBUG -o {toxinidir}/build src
[testenv:venv]
commands = {posargs}
[testenv:pep8]
commands = flake8 {posargs} src/reactive src/lib unit_tests
# Disable py27 tests as this is a reactive python 3 charm. Once project
# config has been updated this tox target can be removed
[testenv:py27]
commands = /bin/true
[testenv:py34]
basepython = python3.4
deps = -r{toxinidir}/test-requirements.txt
commands = ostestr {posargs}
[testenv:py35]
basepython = python3.5
deps = -r{toxinidir}/test-requirements.txt
commands = ostestr {posargs}
[testenv:py36]
basepython = python3.6
deps = -r{toxinidir}/test-requirements.txt
commands = ostestr {posargs}

View File

@ -1,22 +0,0 @@
# Copyright 2016 Canonical Ltd
#
# 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 sys
sys.path.append('src')
sys.path.append('src/lib')
# Mock out charmhelpers so that we can test without it.
import charms_openstack.test_mocks # noqa
charms_openstack.test_mocks.mock_charmhelpers()

View File

@ -1,136 +0,0 @@
# Copyright 2016 Canonical Ltd
#
# 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.
from __future__ import absolute_import
from __future__ import print_function
import mock
import charmhelpers
import charm.openstack.trove as trove
import charms_openstack.test_utils as test_utils
class Helper(test_utils.PatchHelper):
def setUp(self):
super().setUp()
self.patch_release(trove.TroveCharm.release)
class TestOpenStackTrove(Helper):
def _patch_config_and_charm(self, config):
self.patch_object(charmhelpers.core.hookenv, 'config')
def cf(key=None):
if key is not None:
return config[key]
return config
self.config.side_effect = cf
c = trove.TroveCharm()
return c
def test_install(self):
self.patch_object(trove.TroveCharm.singleton, 'install')
trove.install()
self.install.assert_called_once_with()
def test_setup_endpoint(self):
self.patch_object(trove.TroveCharm, 'service_name',
new_callable=mock.PropertyMock)
self.patch_object(trove.TroveCharm, 'region',
new_callable=mock.PropertyMock)
self.patch_object(trove.TroveCharm, 'public_url',
new_callable=mock.PropertyMock)
self.patch_object(trove.TroveCharm, 'internal_url',
new_callable=mock.PropertyMock)
self.patch_object(trove.TroveCharm, 'admin_url',
new_callable=mock.PropertyMock)
self.service_name.return_value = 'type1'
self.region.return_value = 'region1'
self.public_url.return_value = 'public_url'
self.internal_url.return_value = 'internal_url'
self.admin_url.return_value = 'admin_url'
keystone = mock.MagicMock()
trove.setup_endpoint(keystone)
keystone.register_endpoints.assert_called_once_with(
'trove', 'region1', 'public_url/v1.0/%(tenant_id)s',
'internal_url/v1.0/%(tenant_id)s',
'admin_url/v1.0/%(tenant_id)s')
def test_render_configs(self):
self.patch_object(trove.TroveCharm.singleton, 'render_with_interfaces')
trove.render_configs('interfaces-list')
self.render_with_interfaces.assert_called_once_with(
'interfaces-list')
def test_db_sync_done(self):
self.patch_object(trove.TroveCharm, 'db_sync_done')
trove.db_sync_done()
self.db_sync_done.assert_called_once_with()
def test_db_sync(self):
self.patch_object(trove.TroveCharm.singleton, 'db_sync')
trove.db_sync()
self.db_sync.assert_called_once_with()
def test_configure_ha_resources(self):
self.patch_object(trove.TroveCharm.singleton, 'db_sync')
trove.db_sync()
self.db_sync.assert_called_once_with()
def test_restart_all(self):
self.patch_object(trove.TroveCharm.singleton, 'restart_all')
trove.restart_all()
self.restart_all.assert_called_once_with()
def test_configure_ssl(self):
self.patch_object(trove.TroveCharm.singleton, 'configure_ssl')
trove.configure_ssl()
self.configure_ssl.assert_called_once_with(None)
def test_update_peers(self):
self.patch_object(trove.TroveCharm.singleton, 'update_peers')
trove.update_peers('cluster')
self.update_peers.assert_called_once_with('cluster')
def test_assess_status(self):
self.patch_object(trove.TroveCharm.singleton, 'assess_status')
trove.assess_status()
self.assess_status.assert_called_once_with()
def test_get_amqp_credentials(self):
config = {
'rabbit-user': 'rabbit1',
'rabbit-vhost': 'password'
}
c = self._patch_config_and_charm(config)
self.assertEqual(c.get_amqp_credentials(), ('rabbit1', 'password'))
def test_get_database_setup(self):
self.patch_object(charmhelpers.core.hookenv,
'network_get_primary_address')
self.network_get_primary_address.return_value = 'private_ip'
config = {
'database': 'db1',
'database-user': 'user1',
}
c = self._patch_config_and_charm(config)
self.assertEqual(
c.get_database_setup(),
[dict(database='db1', username='user1', hostname='private_ip')])

View File

@ -1,37 +0,0 @@
from __future__ import absolute_import
from __future__ import print_function
import charms_openstack.test_utils as test_utils
import reactive.trove_handlers as handlers
class TestRegisteredHooks(test_utils.TestRegisteredHooks):
def test_hooks(self):
defaults = [
'charm.installed',
'amqp.connected',
'shared-db.connected',
'identity-service.connected',
'identity-service.available', # enables SSL support
'config.changed',
'config.complete',
'db.synced']
hook_set = {
'when': {
'render_stuff': ('shared-db.available',
'identity-service.available',
'amqp.available',),
'update_peers': ('cluster.available',),
'setup_endpoint': ('identity-service.connected',),
'cluster_connected': ('ha.connected',),
'run_db_migration': ('config.complete',),
},
'when_not': {
'run_db_migration': ('db.synced',),
},
}
# test that the hooks were registered via the
# reactive.trove_handlers
self.registered_hooks_test_helper(handlers, hook_set, defaults)