Use bundletester for amulet test execution
Switch to using bundletester for execution of functional tests, leveraging tox to build out test virtualenvs. Rename amulet tests inline with gate-* and dfs-* naming standards. Update README to refer to functional testing section of the charm guide. Drop deprecated tests as no longer used in any automated way. Change-Id: I5fbfb7484ae2fdc5ed10e5a992cedc94df071ee4
This commit is contained in:
parent
94612bf09d
commit
df8742dc74
3
Makefile
3
Makefile
|
@ -30,5 +30,4 @@ test:
|
|||
|
||||
functional_test:
|
||||
@echo Starting amulet tests...
|
||||
@tests/setup/00-setup
|
||||
@juju test -v -p AMULET_HTTP_PROXY,AMULET_OS_VIP --timeout 2700
|
||||
@tox -e func27
|
||||
|
|
|
@ -7,3 +7,17 @@ flake8>=2.2.4,<=2.4.1
|
|||
os-testr>=0.4.1
|
||||
charm-tools>=2.0.0
|
||||
requests==2.6.0
|
||||
# BEGIN: Amulet OpenStack Charm Helper Requirements
|
||||
# Liberty client lower constraints
|
||||
amulet>=1.14.3,<2.0
|
||||
bundletester>=0.6.1,<1.0
|
||||
python-ceilometerclient>=1.5.0,<2.0
|
||||
python-cinderclient>=1.4.0,<2.0
|
||||
python-glanceclient>=1.1.0,<2.0
|
||||
python-heatclient>=0.8.0,<1.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
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
#
|
||||
# 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.
|
||||
|
||||
"""Amulet tests on a basic rabbitmq-server deployment on trusty-juno."""
|
||||
|
||||
from basic_deployment import RmqBasicDeployment
|
||||
|
||||
if __name__ == '__main__':
|
||||
deployment = RmqBasicDeployment(series='trusty',
|
||||
openstack='cloud:trusty-juno',
|
||||
source='cloud:trusty-updates/juno')
|
||||
deployment.run_tests()
|
|
@ -1,23 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
#
|
||||
# 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.
|
||||
|
||||
"""Amulet tests on a basic rabbitmq-server deployment on wily-liberty."""
|
||||
|
||||
from basic_deployment import RmqBasicDeployment
|
||||
|
||||
if __name__ == '__main__':
|
||||
deployment = RmqBasicDeployment(series='wily')
|
||||
deployment.run_tests()
|
113
tests/README
113
tests/README
|
@ -1,113 +0,0 @@
|
|||
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.
|
||||
|
||||
Reference: lp:openstack-charm-testing for full test bundles.
|
||||
|
||||
A single topology and configuration is defined and deployed, once for each of
|
||||
the defined Ubuntu:OpenStack release combos. The ongoing goal is for this
|
||||
charm to always possess tests and combo definitions for all currently-supported
|
||||
release combinations of U:OS.
|
||||
|
||||
test_* methods are called in lexical sort order, as with most runners. However,
|
||||
each individual test method should be idempotent and expected to pass regardless
|
||||
of run order or Ubuntu:OpenStack combo. When writing or modifying tests,
|
||||
ensure that every individual test is not dependent on another test_ method.
|
||||
|
||||
Test naming convention, purely for code organization purposes:
|
||||
1xx service and endpoint checks
|
||||
2xx relation checks
|
||||
3xx config checks
|
||||
4xx functional checks
|
||||
9xx restarts, config changes, actions and other final checks
|
||||
|
||||
In order to run tests, charm-tools and juju must be installed:
|
||||
sudo add-apt-repository ppa:juju/stable
|
||||
sudo apt-get update
|
||||
sudo apt-get install charm-tools juju juju-deployer amulet
|
||||
|
||||
Alternatively, tests may be exercised with proposed or development versions
|
||||
of juju and related tools:
|
||||
|
||||
# juju proposed version
|
||||
sudo add-apt-repository ppa:juju/proposed
|
||||
sudo apt-get update
|
||||
sudo apt-get install charm-tools juju juju-deployer
|
||||
|
||||
# juju development version
|
||||
sudo add-apt-repository ppa:juju/devel
|
||||
sudo apt-get update
|
||||
sudo apt-get install charm-tools juju juju-deployer
|
||||
|
||||
Some tests may need to download files. If a web proxy server is required in
|
||||
the environment, the AMULET_HTTP_PROXY environment variable must be set and
|
||||
passed into the juju test command. This is unrelated to juju's http proxy
|
||||
settings or behavior.
|
||||
|
||||
The following examples demonstrate different ways that tests can be executed.
|
||||
All examples are run from the charm's root directory.
|
||||
|
||||
* To run all +x tests in the tests directory:
|
||||
|
||||
bzr branch lp:charms/trusty/foo
|
||||
cd foo
|
||||
make functional_test
|
||||
|
||||
* To run the tests against a specific release combo as defined in tests/:
|
||||
|
||||
bzr branch lp:charms/trusty/foo
|
||||
cd foo
|
||||
juju test -v -p AMULET_HTTP_PROXY 015-basic-trusty-icehouse
|
||||
|
||||
* To run tests and keep the juju environment deployed after a failure:
|
||||
|
||||
bzr branch lp:charms/trusty/foo
|
||||
cd foo
|
||||
juju test --set-e -v -p AMULET_HTTP_PROXY 015-basic-trusty-icehouse
|
||||
|
||||
* To re-run a test module against an already deployed environment (one
|
||||
that was deployed by a previous call to 'juju test --set-e'):
|
||||
|
||||
./tests/015-basic-trusty-icehouse
|
||||
|
||||
* Even with --set-e, `juju test` will tear down the deployment when all
|
||||
tests pass. The following work flow may be more effective when
|
||||
iterating on test writing.
|
||||
|
||||
bzr branch lp:charms/trusty/foo
|
||||
cd foo
|
||||
./tests/setup/00-setup
|
||||
juju bootstrap
|
||||
./tests/015-basic-trusty-icehouse
|
||||
# make some changes, run tests again
|
||||
./tests/015-basic-trusty-icehouse
|
||||
# make some changes, run tests again
|
||||
./tests/015-basic-trusty-icehouse
|
||||
|
||||
* There may be test definitions in the tests/ dir which are not set +x
|
||||
executable. This is generally true for deprecated releases, or for
|
||||
upcoming releases which are not yet validated and enabled. To enable
|
||||
and run these tests:
|
||||
bzr branch lp:charms/trusty/foo
|
||||
cd foo
|
||||
ls tests
|
||||
chmod +x tests/017-basic-trusty-kilo
|
||||
./tests/setup/00-setup
|
||||
juju bootstrap
|
||||
./tests/017-basic-trusty-kilo
|
||||
|
||||
|
||||
Additional notes:
|
||||
|
||||
* Use DEBUG to turn on debug logging, use ERROR otherwise.
|
||||
u = OpenStackAmuletUtils(ERROR)
|
||||
u = OpenStackAmuletUtils(DEBUG)
|
||||
|
||||
* To interact with the deployed environment:
|
||||
export OS_USERNAME=admin
|
||||
export OS_PASSWORD=openstack
|
||||
export OS_TENANT_NAME=admin
|
||||
export OS_REGION_NAME=RegionOne
|
||||
export OS_AUTH_URL=${OS_AUTH_PROTOCOL:-http}://`juju-deployer -e trusty -f keystone`:5000/v2.0
|
||||
keystone user-list
|
||||
glance image-list
|
|
@ -0,0 +1,9 @@
|
|||
# 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.
|
|
@ -130,13 +130,13 @@ class RmqBasicDeployment(OpenStackAmuletDeployment):
|
|||
def _initialize_tests(self):
|
||||
"""Perform final initialization before tests get run."""
|
||||
# Access the sentries for inspecting service units
|
||||
self.rmq0_sentry = self.d.sentry.unit['rabbitmq-server/0']
|
||||
self.rmq1_sentry = self.d.sentry.unit['rabbitmq-server/1']
|
||||
self.rmq2_sentry = self.d.sentry.unit['rabbitmq-server/2']
|
||||
self.keystone_sentry = self.d.sentry.unit['keystone/0']
|
||||
self.mysql_sentry = self.d.sentry.unit['mysql/0']
|
||||
self.cinder_sentry = self.d.sentry.unit['cinder/0']
|
||||
self.nrpe_sentry = self.d.sentry.unit['nrpe/0']
|
||||
self.rmq0_sentry = self.d.sentry['rabbitmq-server'][0]
|
||||
self.rmq1_sentry = self.d.sentry['rabbitmq-server'][1]
|
||||
self.rmq2_sentry = self.d.sentry['rabbitmq-server'][2]
|
||||
self.keystone_sentry = self.d.sentry['keystone'][0]
|
||||
self.mysql_sentry = self.d.sentry['mysql'][0]
|
||||
self.cinder_sentry = self.d.sentry['cinder'][0]
|
||||
self.nrpe_sentry = self.d.sentry['nrpe'][0]
|
||||
u.log.debug('openstack release val: {}'.format(
|
||||
self._get_openstack_release()))
|
||||
u.log.debug('openstack release str: {}'.format(
|
||||
|
@ -592,16 +592,13 @@ class RmqBasicDeployment(OpenStackAmuletDeployment):
|
|||
def test_910_pause_and_resume(self):
|
||||
"""The services can be paused and resumed. """
|
||||
u.log.debug('Checking pause and resume actions...')
|
||||
unit_name = "rabbitmq-server/0"
|
||||
unit = self.d.sentry.unit[unit_name]
|
||||
assert u.status_get(self.rmq0_sentry)[0] == "active"
|
||||
|
||||
assert u.status_get(unit)[0] == "active"
|
||||
action_id = u.run_action(self.rmq0_sentry, "pause")
|
||||
assert u.wait_on_action(action_id), "Pause action failed."
|
||||
assert u.status_get(self.rmq0_sentry)[0] == "maintenance"
|
||||
|
||||
action_id = self._run_action(unit_name, "pause")
|
||||
assert self._wait_on_action(action_id), "Pause action failed."
|
||||
assert u.status_get(unit)[0] == "maintenance"
|
||||
|
||||
action_id = self._run_action(unit_name, "resume")
|
||||
assert self._wait_on_action(action_id), "Resume action failed."
|
||||
assert u.status_get(unit)[0] == "active"
|
||||
action_id = u.run_action(self.rmq0_sentry, "resume")
|
||||
assert u.wait_on_action(action_id), "Resume action failed."
|
||||
assert u.status_get(self.rmq0_sentry)[0] == "active"
|
||||
u.log.debug('OK')
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Install Juju Amulet and any other applications that are needed for the tests.
|
||||
|
||||
set -x
|
||||
|
||||
# Check if amulet is installed before adding repository and updating apt-get.
|
||||
dpkg -s amulet
|
||||
if [ $? -ne 0 ]; then
|
||||
sudo add-apt-repository -y ppa:juju/stable
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y amulet
|
||||
fi
|
||||
|
||||
# Install any additional python packages, or software here.
|
||||
sudo apt-get install -y python python-pika python3-requests python3-setuptools
|
||||
|
||||
# Set http proxy if amulet is using one.
|
||||
[[ -n "$AMULET_HTTP_PROXY" ]] && export http_proxy="$AMULET_HTTP_PROXY" && export https_proxy="$AMULET_HTTP_PROXY"
|
||||
|
||||
sudo easy_install3 python3-pika
|
|
@ -1,30 +0,0 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
import amulet
|
||||
import pika
|
||||
|
||||
d = amulet.Deployment(series='trusty')
|
||||
|
||||
d.add('rabbitmq-server')
|
||||
d.expose('rabbitmq-server')
|
||||
|
||||
# Don't forget to expose using d.expose(service)
|
||||
|
||||
try:
|
||||
d.setup(timeout=3000)
|
||||
d.sentry.wait()
|
||||
except amulet.helpers.TimeoutError:
|
||||
amulet.raise_status(amulet.SKIP, msg="Environment wasn't stood up in time")
|
||||
except:
|
||||
raise
|
||||
|
||||
server = d.sentry.unit['rabbitmq-server/0']
|
||||
host = server.info['public-address']
|
||||
|
||||
try:
|
||||
connection = pika.BlockingConnection(pika.ConnectionParameters(host=host))
|
||||
except Exception as e:
|
||||
amulet.raise_status(
|
||||
amulet.FAIL,
|
||||
str(e)
|
||||
)
|
|
@ -1,92 +0,0 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
# This Amulet test performs a basic deploy and checks if rabbitmq is running.
|
||||
|
||||
import amulet
|
||||
import os
|
||||
import socket
|
||||
import ssl
|
||||
from deploy_common import CA
|
||||
|
||||
# The number of seconds to wait for the environment to setup.
|
||||
seconds = 900
|
||||
# Get the directory in this way to load the files from the tests directory.
|
||||
path = os.path.abspath(os.path.dirname(__file__))
|
||||
|
||||
ca = CA()
|
||||
|
||||
# Create a dictionary for the rabbitmq configuration.
|
||||
rabbitmq_configuration = {
|
||||
'ssl_enabled': True,
|
||||
'ssl_key': ca.get_key(),
|
||||
'ssl_cert': ca.get_cert(),
|
||||
'ssl_port': 5671
|
||||
}
|
||||
|
||||
d = amulet.Deployment(series='trusty')
|
||||
# Add the rabbitmq-server charm to the deployment.
|
||||
d.add('rabbitmq-server')
|
||||
# Configure options on the rabbitmq-server.
|
||||
d.configure('rabbitmq-server', rabbitmq_configuration)
|
||||
# Expose the server so we can connect.
|
||||
d.expose('rabbitmq-server')
|
||||
|
||||
try:
|
||||
# Execute the deployer with the current mapping.
|
||||
d.setup(timeout=seconds)
|
||||
except amulet.helpers.TimeoutError:
|
||||
message = 'The environment did not setup in %d seconds.' % seconds
|
||||
# The SKIP status enables skip or fail the test based on configuration.
|
||||
amulet.raise_status(amulet.SKIP, msg=message)
|
||||
except:
|
||||
raise
|
||||
print('The rabbitmq-server has been successfully deployed.')
|
||||
|
||||
###############################################################################
|
||||
# Verify that the rabbit service is running on the deployed server.
|
||||
###############################################################################
|
||||
rabbitmq_sentry = d.sentry.unit['rabbitmq-server/0']
|
||||
# Get the public address for rabbitmq-server instance.
|
||||
server_address = rabbitmq_sentry.info['public-address']
|
||||
# Create the command that checks if the rabbitmq-server service is running.
|
||||
command = 'rabbitmqctl status'
|
||||
print(command)
|
||||
# Execute the command on the deployed service.
|
||||
output, code = rabbitmq_sentry.run(command)
|
||||
print(output)
|
||||
# Check the return code for the success and failure of this test.
|
||||
if (code != 0):
|
||||
message = 'The ' + command + ' did not return the expected code of 0.'
|
||||
amulet.raise_status(amulet.FAIL, msg=message)
|
||||
else:
|
||||
print('The rabbitmq-server is running on %s' % server_address)
|
||||
|
||||
###############################################################################
|
||||
# Test the ssl certificate.
|
||||
###############################################################################
|
||||
# Get the port for ssl_port instance.
|
||||
server_port = rabbitmq_configuration['ssl_port']
|
||||
|
||||
print('Testing ssl connection to rabbitmq-server.')
|
||||
try:
|
||||
# Create a normal socket.
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
# Require a certificate from the server, since a self-signed certificate
|
||||
# was used, the ca_certs must be the server certificate file itself.
|
||||
ssl_sock = ssl.wrap_socket(s, ca_certs=ca.ca_cert_path(),
|
||||
cert_reqs=ssl.CERT_REQUIRED)
|
||||
# Connect to the rabbitmq server using ssl.
|
||||
ssl_sock.connect((server_address, server_port))
|
||||
# Get the certificate.
|
||||
certificate = ssl_sock.getpeercert()
|
||||
# SSL socket connected and got the certificate, this passes the ssl test!
|
||||
print('Connected to the rabbitmq-server {0}:{1} using ssl!'.format(
|
||||
server_address, server_port))
|
||||
except Exception as e:
|
||||
message = 'Failed to create an ssl connection to {0}:{1}\n{2}'.format(
|
||||
server_address, server_port, str(e))
|
||||
amulet.raise_status(amulet.FAIL, msg=message)
|
||||
finally:
|
||||
ssl_sock.close()
|
||||
|
||||
print('The rabbitmq-server passed the basic deploy test!')
|
|
@ -1,94 +0,0 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
import amulet
|
||||
import os
|
||||
import pika
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
# The juju environment should be bootstrapped at this point, but depending
|
||||
# on the test environment an http proxy may be necessary. Check to see if
|
||||
# one is configured via the environment variable and set it if it is.
|
||||
# The settings of these proxy variables should only survive the current
|
||||
# lifetime of the bootstrapped environment and will be torn down for the
|
||||
# next test.
|
||||
if os.environ.get('AMULET_HTTP_PROXY', None):
|
||||
proxy_setting = 'http-proxy={}'.format(os.environ['AMULET_HTTP_PROXY'])
|
||||
subprocess.call(['juju', 'set-env', proxy_setting])
|
||||
|
||||
if os.environ.get('AMULET_HTTPS_PROXY', None):
|
||||
proxy_setting = 'https-proxy={}'.format(os.environ['AMULET_HTTPS_PROXY'])
|
||||
subprocess.call(['juju', 'set-env', proxy_setting])
|
||||
|
||||
|
||||
d = amulet.Deployment(series='trusty')
|
||||
|
||||
d.add('rabbitmq-server')
|
||||
d.configure('rabbitmq-server', {
|
||||
"source": "deb http://www.rabbitmq.com/debian/ testing main",
|
||||
"key": """-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Version: GnuPG v1.4.6 (GNU/Linux)
|
||||
|
||||
mQGiBEaOQ/IRBACs/n609zN+OzlK9qDkFWwYKfPG+BlgqBj5MSy0XE2K8cE3bWSV
|
||||
2WftTe/TGEfW0hknXt1PyBla0cnO9Up1xCn142vo8bvUug8WjrxLQBBiAf11FAOR
|
||||
dt9roGe4IWw/Lakgb88re09ZYKmOL9H7MEpvMqtjdWjFSq4zeeGa8rGEswCgnQLb
|
||||
ZD/MNlUNQwQVCs+vVRdgpzcD+QELSc2EeYl4tef0NiUaZQt+mjFTs3DjQNDTjXao
|
||||
ETVAqECx4kavcshx5tSE5JbbQPIMiUgh0h9J3z3uZsBVnx6P82aW/QTw+jLhsQry
|
||||
/i3Z/+pS66mk6EWhAAYF/SPVqM/06BZh0ZvUmeG9WGGJXD9CUN1Wfi2mt42L2zhT
|
||||
xg3uBACoIs5/GORi0H2i+blLiFSxTroXw+TdxiP+mfjdPho0oXJQTljXBgG70VfX
|
||||
XW9sWsYtekqXBsmwMcbCZTjZGul/8jAUlUoYfthRw9KpP9N8Q7wB8Flx9jEv0M0H
|
||||
tV1KTrLuXNZvEAB1sECMa7RRrV1yO4wyYDsOXiZNTL6rYugOU7QwUmFiYml0TVEg
|
||||
UmVsZWFzZSBTaWduaW5nIEtleSA8aW5mb0ByYWJiaXRtcS5jb20+iGAEExECACAF
|
||||
AkaOQ/ICGwMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAKCRD3uM6mBW6OVkymAJ0R
|
||||
6MwiZNRuTAttgYf1Xe7dK7HpzACfZioV/LqnDh7XvcTJEl+r4GB19by5Ag0ERo5D
|
||||
+xAIAKu1ZxtAZjwlNLb0L5uwrEP7nTbRTNUYoEtE8+CNDSLLlmRIvBriKYNGicnz
|
||||
Ebq2kDnAoyH38ACIMNayrkqc6I4l3BD2sv7zPZCd4qAbyFCu6gnewTANTWkVuH60
|
||||
R65QQ8pM8sM+VZAMSoMkDSP4u248xOzFyGgVYuuWuR/sIRcaA02FW9TGvZQ7fNoF
|
||||
rf6UbKSYkjpY767IW8q0b68vKzSLw0GQvH+dsvhaj80hjKJ06+IZ9Gdi/b4+AIT2
|
||||
YWyWmrHo2QhnUmsarNdtusesQGQtiYgZw95PJJkzR0AttuPPfPNGLYZtVJenvOCC
|
||||
jsK5uUL3/eEQ3UWGs+BKEyA/qLMAAwUH/2kIFCdgCw2DnL87TO+vruhGjsM7NjXf
|
||||
57F4ojTdblFd6AerjRhMgICdzCF9WkFROdBSyQ/GajoNU81kbHZglxmKyKkVwWEb
|
||||
G7pmSIc/sk5Z7OP/zrg4h8ZGzvMbRy0XLf86lQhbDE3AcHMeJCcShIWAHAbygnYW
|
||||
j0KRhZiyqxqx4mrZQDZEWI7S1G9YNvgu1GS9EEKEpmxDEOME9nJZLi9o7mTeD1QV
|
||||
TyOzWHkpQ42QcgrFuG7RMxDaQK6bdinNTl8aPmMoPamGzotSt4aMoVMiNxjatnlH
|
||||
pqQ5UJlqbB5FGLnwJ0773WzgRdxIwSIxkFhL/Mq4agf4an8151kqcZCISQQYEQIA
|
||||
CQUCRo5D+wIbDAAKCRD3uM6mBW6OVhLmAKCYY152B/10n7aUNKejs92NsNAnPACf
|
||||
ZwbDOKBXGfkCPuRx5j/AGneASNU=
|
||||
=Ry+c
|
||||
-----END PGP PUBLIC KEY BLOCK-----""",
|
||||
"management_plugin": True,
|
||||
})
|
||||
d.expose('rabbitmq-server')
|
||||
|
||||
# Don't forget to expose using d.expose(service)
|
||||
|
||||
try:
|
||||
# TODO(billy-olsen), juju test --timeout fails to pass the timeout values
|
||||
# into the environment and the charm isn't the best of places to select
|
||||
# a viable timeout since so muc is attributed to the environment anyways.
|
||||
# Need to fix this the right way, but for now we'll bump the timeout.
|
||||
d.setup(timeout=2700)
|
||||
d.sentry.wait()
|
||||
except amulet.helpers.TimeoutError:
|
||||
amulet.raise_status(amulet.SKIP, msg="Environment wasn't stood up in time")
|
||||
except:
|
||||
raise
|
||||
|
||||
server = d.sentry.unit['rabbitmq-server/0']
|
||||
host = server.info['public-address']
|
||||
|
||||
# TODO(wolsen) It looks like in rabbitmq version 3.3.0 the guest count was
|
||||
# disabled by default and therefore we need to do the following bit of code
|
||||
# in order to allow guest access for the test to succeed.
|
||||
server.run('echo "[{rabbit, [{loopback_users, []}]}]." > '
|
||||
'/etc/rabbitmq/rabbitmq.config')
|
||||
server.run('service rabbitmq-server restart')
|
||||
|
||||
|
||||
try:
|
||||
connection = pika.BlockingConnection(pika.ConnectionParameters(host=host))
|
||||
except Exception as e:
|
||||
amulet.raise_status(
|
||||
amulet.FAIL,
|
||||
str(e)
|
||||
)
|
|
@ -1,251 +0,0 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
# This Amulet test deploys rabbitmq-server, and the related charms.
|
||||
|
||||
import amulet
|
||||
import os
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
# The number of seconds to wait for the environment to setup.
|
||||
seconds = 2700
|
||||
# The number of units to scale rabbitmq-server to.
|
||||
scale = 2
|
||||
# The port that amqp traffic is sent on.
|
||||
amqp_port = '5672'
|
||||
# The directory to use as a block devie for the ceph
|
||||
devices = '/srv/osd1'
|
||||
# The default version of ceph does not support directories as devices.
|
||||
havana = 'cloud:precise-updates/havana'
|
||||
# Create a dictionary of configuration values for ceph.
|
||||
ceph_configuration = {
|
||||
'fsid': 'ecbb8960-0e21-11e2-b495-83a88f44db01',
|
||||
'monitor-secret': 'AQBomftSyK1LORAAhg71ukxBxN9ml90stexqEw==',
|
||||
'osd-devices': devices,
|
||||
'source': havana
|
||||
}
|
||||
# Create a dictionary of configuration values for cinder.
|
||||
cinder_configuration = {
|
||||
'block-device': 'None'
|
||||
}
|
||||
# Create a dictionary of the rabbit configuration values.
|
||||
rabbit_configuration = {
|
||||
'vip': '192.168.77.11',
|
||||
'vip_cidr': 19,
|
||||
'vip_iface': 'eth0',
|
||||
'ha-bindiface': 'eth0',
|
||||
'ha-mcastport': 5406,
|
||||
'rbd-size': '2G',
|
||||
'rbd-name': 'testrabbit1'
|
||||
}
|
||||
|
||||
# The AMQP package is only available for python version 2.x.
|
||||
python2 = '/usr/bin/python'
|
||||
if not os.path.isfile(python2):
|
||||
error_message = 'Error, python version 2 is required for this test.'
|
||||
amulet.raise_status(amulet.FAIL, msg=error_message)
|
||||
|
||||
series = 'trusty'
|
||||
d = amulet.Deployment(series=series)
|
||||
# Add rabbitmq-server to the deployment.
|
||||
d.add('rabbitmq-server', units=scale)
|
||||
|
||||
# TODO(billy-olsen) - Rework this following set of code to be more in-line
|
||||
# with how the other openstack services are done. For now, we want to test
|
||||
# the current branch with the appropriate branches of related charms in
|
||||
# order to test /next with /next branches and /trunk with /trunk branches.
|
||||
stable = False
|
||||
|
||||
|
||||
def determine_charm_branches(services):
|
||||
if stable:
|
||||
for svc in services:
|
||||
temp = 'lp:charms/{}'
|
||||
svc['location'] = temp.format(svc['name'])
|
||||
else:
|
||||
for svc in services:
|
||||
temp = 'lp:~openstack-charmers/charms/{}/{}/next'
|
||||
svc['location'] = temp.format(series, svc['name'])
|
||||
|
||||
return services
|
||||
|
||||
|
||||
def add_services(services):
|
||||
"""
|
||||
Adds services to the deployment. The input is a list of dicts with
|
||||
the key of 'name' name for the service name. The branch location
|
||||
will be determined automatically.
|
||||
"""
|
||||
services = determine_charm_branches(services)
|
||||
|
||||
for svc in services:
|
||||
d.add(svc['name'], charm=svc['location'])
|
||||
|
||||
|
||||
services_to_add = [
|
||||
{'name': 'ceph'},
|
||||
{'name': 'cinder'},
|
||||
{'name': 'hacluster'},
|
||||
]
|
||||
|
||||
# Add the services to the deployment
|
||||
add_services(services_to_add)
|
||||
|
||||
# The ceph charm requires configuration to deploy successfully.
|
||||
d.configure('ceph', ceph_configuration)
|
||||
# Configure the cinder charm.
|
||||
d.configure('cinder', cinder_configuration)
|
||||
# Configure the rabbit charm.
|
||||
d.configure('rabbitmq-server', rabbit_configuration)
|
||||
# Add relation from rabbitmq-server to ceph testing the ceph relation.
|
||||
d.relate('rabbitmq-server:ceph', 'ceph:client')
|
||||
# Add relation from rabbitmq-server to cinder testing the amqp relation.
|
||||
d.relate('rabbitmq-server:amqp', 'cinder:amqp')
|
||||
# Add relation from rabibtmq-server to hacluster testing the ha relation.
|
||||
d.relate('rabbitmq-server:ha', 'hacluster:ha')
|
||||
# Expose the rabbitmq-server.
|
||||
d.expose('rabbitmq-server')
|
||||
|
||||
try:
|
||||
# Execute the deployer with the current mapping.
|
||||
d.setup(timeout=seconds)
|
||||
# Wait for the relation to finish the transations.
|
||||
d.sentry.wait(seconds)
|
||||
except amulet.helpers.TimeoutError:
|
||||
message = 'The environment did not setup in %d seconds.' % seconds
|
||||
# The SKIP status enables skip or fail the test based on configuration.
|
||||
amulet.raise_status(amulet.FAIL, msg=message)
|
||||
except:
|
||||
raise
|
||||
print('The environment successfully deployed.')
|
||||
|
||||
# Create a counter to make the messages unique.
|
||||
counter = 1
|
||||
# Get the directory in this way to load the files from the tests directory.
|
||||
path = os.path.abspath(os.path.dirname(__file__))
|
||||
# Create a path to the python test file to call.
|
||||
amqp_tester = os.path.join(path, 'amqp_tester.py')
|
||||
if not os.path.isfile(amqp_tester):
|
||||
error_message = 'Unable to locate python test file %s' % amqp_tester
|
||||
amulet.raise_status(amulet.FAIL, msg=error_message)
|
||||
|
||||
# Verify the ceph unit was created.
|
||||
ceph_unit = d.sentry.unit['ceph/0']
|
||||
# Verify the cinder unit was created.
|
||||
cinder_unit = d.sentry.unit['cinder/0']
|
||||
rabbit_units = []
|
||||
for n in range(scale):
|
||||
# Get each rabbitmq unit that was deployed.
|
||||
rabbit_units.append(d.sentry.unit['rabbitmq-server/%d' % n])
|
||||
|
||||
# Iterate over every rabbitmq-unit to get the different relations.
|
||||
for rabbit_unit in rabbit_units:
|
||||
###########################################################################
|
||||
# Test Relations
|
||||
###########################################################################
|
||||
# Verify the ceph relation was created for the rabbit unit.
|
||||
rabbit_relation = rabbit_unit.relation('ceph', 'ceph:client')
|
||||
print('rabbit relation to ceph:')
|
||||
for key, value in rabbit_relation.items():
|
||||
print(key, value)
|
||||
# Verify the amqp relation was created for the rabbit unit.
|
||||
rabbit_relation = rabbit_unit.relation('amqp', 'cinder:amqp')
|
||||
print('rabbit relation to amqp:')
|
||||
for key, value in rabbit_relation.items():
|
||||
print(key, value)
|
||||
|
||||
# The hacluster charm is a subordinate, since the relation-sentry is also
|
||||
# a subordinate charm no sentry is created for the hacluster relation.
|
||||
|
||||
# Verify the rabbit relation was created with the ceph unit.
|
||||
ceph_relation = ceph_unit.relation('client', 'rabbitmq-server:ceph')
|
||||
print('ceph relation to rabbitmq-server:')
|
||||
for key, value in ceph_relation.items():
|
||||
print(key, value)
|
||||
# Verify the rabbit relation was created with the cinder unit.
|
||||
cinder_relation = cinder_unit.relation('amqp', 'rabbitmq-server:amqp')
|
||||
print('cinder relation to rabbitmq-server:')
|
||||
for key, value in cinder_relation.items():
|
||||
print(key, value)
|
||||
|
||||
###########################################################################
|
||||
# Test AMQP
|
||||
###########################################################################
|
||||
|
||||
# The AMQP python library is only available for python2 at this time.
|
||||
# Call out a command to run the python2 code to test the AMQP protocol.
|
||||
|
||||
# Get the public address for rabbitmq-server instance.
|
||||
server_address = rabbit_unit.info['public-address']
|
||||
# Create a time stamp to help make the AMQP message unique.
|
||||
time_stamp = time.strftime('%F %r')
|
||||
# Create the message to send on the AMPQ protocol.
|
||||
amqp_message = "Message #{0} to send using the AMPQ protocol {1}".format(
|
||||
counter, time_stamp)
|
||||
# Create the command with arguments that sends the message.
|
||||
send_command = [python2, amqp_tester, server_address, amqp_port,
|
||||
amqp_message]
|
||||
print(send_command)
|
||||
# Call the python command to send the AMQP message to the server.
|
||||
output = subprocess.check_output(send_command)
|
||||
# Create the command with arguments to receive messages.
|
||||
receive_command = [python2, amqp_tester, server_address, amqp_port]
|
||||
print(receive_command)
|
||||
# Call the python command to receive the AMQP message from the same server.
|
||||
output = subprocess.check_output(receive_command)
|
||||
# The output is a byte string so convert the message to a byte string.
|
||||
if output.find(amqp_message.encode()) == -1:
|
||||
print('The AMQP test to {0}:{1} failed.'.format(server_address,
|
||||
amqp_port))
|
||||
amulet.raise_status(amulet.FAIL, msg=output)
|
||||
else:
|
||||
print('The AMQP test to {0}:{1} completed successfully.'.format(
|
||||
server_address, amqp_port))
|
||||
counter += 1
|
||||
|
||||
###########################################################################
|
||||
# Verify that the rabbitmq cluster status is correct.
|
||||
###########################################################################
|
||||
# Create the command that checks if the rabbitmq-server service is running.
|
||||
command = 'rabbitmqctl cluster_status'
|
||||
print(command)
|
||||
# Execute the command on the deployed service.
|
||||
output, code = rabbit_unit.run(command)
|
||||
print(output)
|
||||
# Check the return code for the success and failure of this test.
|
||||
if (code != 0):
|
||||
message = 'The ' + command + ' did not return the expected code of 0.'
|
||||
amulet.raise_status(amulet.FAIL, msg=message)
|
||||
else:
|
||||
print('The rabbitmq-server cluster status is OK.')
|
||||
|
||||
###############################################################################
|
||||
# Test the AMQP messages can be sent from and read from another.
|
||||
###############################################################################
|
||||
# Get the public address for rabbitmq-server instance 0.
|
||||
send_address = rabbit_units[0].info['public-address']
|
||||
# Create a message to send from instance 0 and read it from instance 1.
|
||||
amqp_message = "Message #{0} sent from {1} using the AMQP protocol.".format(
|
||||
counter, send_address)
|
||||
counter += 1
|
||||
# Create the command that sends the message to instance 0.
|
||||
send_command = [python2, amqp_tester, send_address, amqp_port, amqp_message]
|
||||
print(send_command)
|
||||
output = subprocess.check_output(send_command)
|
||||
# Get the public address for rabbitmq-server instance 1.
|
||||
receive_address = rabbit_units[1].info['public-address']
|
||||
# Create the command that receives the message from instance 1.
|
||||
recieve_command = [python2, amqp_tester, receive_address, amqp_port]
|
||||
print(recieve_command)
|
||||
output = subprocess.check_output(receive_command)
|
||||
# The output is a byte string so convert the message to a byte string.
|
||||
if output.find(amqp_message.encode()) == -1:
|
||||
print(output)
|
||||
message = 'Server {0} did not receive the AMQP message "{1}"'.format(
|
||||
receive_address, amqp_message)
|
||||
amulet.raise_status(amulet.FAIL, msg=message)
|
||||
else:
|
||||
print('Server {0} received the AMQP message sent from {1}'.format(
|
||||
receive_address, send_address))
|
||||
|
||||
print('The rabbitmq-server charm passed this relations test.')
|
|
@ -1,117 +0,0 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
import amulet
|
||||
import pika
|
||||
import time
|
||||
|
||||
d = amulet.Deployment(series='trusty')
|
||||
|
||||
d.add('rabbitmq-server')
|
||||
d.expose('rabbitmq-server')
|
||||
|
||||
# Don't forget to expose using d.expose(service)
|
||||
|
||||
try:
|
||||
# TODO(billy-olsen), juju test --timeout fails to pass the timeout values
|
||||
# into the environment and the charm isn't the best of places to select
|
||||
# a viable timeout since so muc is attributed to the environment anyways.
|
||||
# Need to fix this the right way, but for now we'll bump the timeout.
|
||||
d.setup(timeout=2700)
|
||||
d.sentry.wait()
|
||||
except amulet.helpers.TimeoutError:
|
||||
amulet.raise_status(amulet.SKIP, msg="Environment wasn't stood up in time")
|
||||
except:
|
||||
raise
|
||||
|
||||
server = d.sentry.unit['rabbitmq-server/0']
|
||||
host = server.info['public-address']
|
||||
|
||||
|
||||
# Connects without ssl
|
||||
try:
|
||||
connection = pika.BlockingConnection(pika.ConnectionParameters(host=host,
|
||||
ssl=False))
|
||||
except Exception as e:
|
||||
amulet.raise_status(
|
||||
amulet.FAIL,
|
||||
"Insecure connection failed with ssl=off: {}".format(str(e))
|
||||
)
|
||||
|
||||
# Doesn't connect with ssl
|
||||
try:
|
||||
connection = pika.BlockingConnection(pika.ConnectionParameters(host=host,
|
||||
ssl=True))
|
||||
except Exception as e:
|
||||
pass
|
||||
else:
|
||||
amulet.raise_status(
|
||||
amulet.FAIL,
|
||||
'SSL enabled when it shouldn\'t.'
|
||||
)
|
||||
|
||||
d.configure('rabbitmq-server', {
|
||||
'ssl': 'on'
|
||||
})
|
||||
|
||||
# There's a race for changing the configuration of a deployment.
|
||||
# The configure from the juju client side happens fairly quickly, and the
|
||||
# sentry.wait() can fire before the config-changed hooks do, which causes
|
||||
# the wait to end...
|
||||
time.sleep(10)
|
||||
d.sentry.wait()
|
||||
|
||||
# Connects without ssl
|
||||
try:
|
||||
connection = pika.BlockingConnection(pika.ConnectionParameters(host=host,
|
||||
ssl=False))
|
||||
except Exception as e:
|
||||
amulet.raise_status(
|
||||
amulet.FAIL,
|
||||
"Insecure connection fails with ssl=on: {}".format(str(e))
|
||||
)
|
||||
|
||||
# Connects with ssl
|
||||
try:
|
||||
connection = pika.BlockingConnection(pika.ConnectionParameters(host=host,
|
||||
port=5671,
|
||||
ssl=True))
|
||||
except Exception as e:
|
||||
amulet.raise_status(
|
||||
amulet.FAIL,
|
||||
"Secure connection fails with ssl=on"
|
||||
)
|
||||
|
||||
d.configure('rabbitmq-server', {
|
||||
'ssl': 'only'
|
||||
})
|
||||
|
||||
# There's a race for changing the configuration of a deployment.
|
||||
# The configure from the juju client side happens fairly quickly, and the
|
||||
# sentry.wait() can fire before the config-changed hooks do, which causes
|
||||
# the wait to end...
|
||||
time.sleep(10)
|
||||
d.sentry.wait()
|
||||
|
||||
|
||||
# Doesn't connect without ssl
|
||||
try:
|
||||
connection = pika.BlockingConnection(pika.ConnectionParameters(host=host,
|
||||
ssl=False))
|
||||
except Exception as e:
|
||||
pass
|
||||
else:
|
||||
amulet.raise_status(
|
||||
amulet.FAIL,
|
||||
"Connects without SSL when it shouldn't"
|
||||
)
|
||||
|
||||
# Connects with ssl
|
||||
try:
|
||||
connection = pika.BlockingConnection(pika.ConnectionParameters(host=host,
|
||||
port=5671,
|
||||
ssl=True))
|
||||
except Exception as e:
|
||||
amulet.raise_status(
|
||||
amulet.FAIL,
|
||||
"Secure connection fails with ssl=only: {}".format(str(e))
|
||||
)
|
|
@ -1,118 +0,0 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
# This Amulet test exercises the configuration options for rabbitmq-server.
|
||||
|
||||
import amulet
|
||||
import os
|
||||
import socket
|
||||
import ssl
|
||||
from deploy_common import CA
|
||||
|
||||
# The number of seconds to wait for the environment to setup.
|
||||
seconds = 2700
|
||||
# Get the directory in this way to load the files from the tests directory.
|
||||
path = os.path.abspath(os.path.dirname(__file__))
|
||||
|
||||
ca = CA()
|
||||
|
||||
privateKey = ca.get_key()
|
||||
certificate = ca.get_cert()
|
||||
|
||||
# Create a dictionary of all the configuration values.
|
||||
rabbit_configuration = {
|
||||
'management_plugin': True,
|
||||
'ssl_enabled': True,
|
||||
'ssl_port': 5999,
|
||||
'ssl_key': privateKey,
|
||||
'ssl_cert': certificate,
|
||||
}
|
||||
|
||||
d = amulet.Deployment(series='trusty')
|
||||
# Add the rabbitmq-server charm to the deployment.
|
||||
d.add('rabbitmq-server')
|
||||
# Configure all the options on rabbitmq-server.
|
||||
d.configure('rabbitmq-server', rabbit_configuration)
|
||||
# Expose the rabbitmq-server.
|
||||
d.expose('rabbitmq-server')
|
||||
|
||||
try:
|
||||
# Execute the deployer with the current mapping.
|
||||
d.setup(timeout=seconds)
|
||||
# Wait for the relation to finish the transations.
|
||||
d.sentry.wait(seconds)
|
||||
except amulet.helpers.TimeoutError:
|
||||
message = 'The environment did not setup in %d seconds.' % seconds
|
||||
# The SKIP status enables skip or fail the test based on configuration.
|
||||
amulet.raise_status(amulet.SKIP, msg=message)
|
||||
except:
|
||||
raise
|
||||
|
||||
rabbit_unit = d.sentry.unit['rabbitmq-server/0']
|
||||
###############################################################################
|
||||
# Verify that the rabbit service is running on the deployed server.
|
||||
###############################################################################
|
||||
# Create the command that checks if the rabbitmq-server service is running.
|
||||
command = 'rabbitmqctl status'
|
||||
print(command)
|
||||
# Execute the command on the deployed service.
|
||||
output, code = rabbit_unit.run(command)
|
||||
print(output)
|
||||
# Check the return code for the success and failure of this test.
|
||||
if (code != 0):
|
||||
message = 'The ' + command + ' did not return the expected code of 0.'
|
||||
amulet.raise_status(amulet.FAIL, msg=message)
|
||||
else:
|
||||
print('The rabbitmq-server is running.')
|
||||
|
||||
###############################################################################
|
||||
# Verify the configuration values.
|
||||
###############################################################################
|
||||
# Get the contents of the private key from the rabbitmq-server
|
||||
contents = rabbit_unit.file_contents('/etc/rabbitmq/rabbit-server-privkey.pem')
|
||||
# Verify the private key was saved on the rabbitmq server correctly.
|
||||
if contents != privateKey:
|
||||
message = 'The private keys did not match!'
|
||||
amulet.raise_status(amulet.FAIL, msg=message)
|
||||
else:
|
||||
print('The private keys was configured properly on the rabbitmq server.')
|
||||
|
||||
# Get the contents of the certificate from the rabbitmq-server.
|
||||
contents = rabbit_unit.file_contents('/etc/rabbitmq/rabbit-server-cert.pem')
|
||||
# Verify the certificate was saved on the rabbitmq server correctly.
|
||||
if contents != certificate:
|
||||
message = 'The certificates did not match!'
|
||||
amulet.raise_status(amulet.FAIL, msg=message)
|
||||
else:
|
||||
print('The certificate was configured properly on the rabbitmq server.')
|
||||
|
||||
# Get the public address for rabbitmq-server instance.
|
||||
rabbit_host = rabbit_unit.info['public-address']
|
||||
|
||||
###############################################################################
|
||||
# Verify that SSL is set up on the non-default port.
|
||||
###############################################################################
|
||||
# Get the port for ssl_port instance.
|
||||
ssl_port = rabbit_configuration['ssl_port']
|
||||
|
||||
try:
|
||||
# Create a normal socket.
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
# Require a certificate from the server, since a self-signed certificate
|
||||
# was used, the ca_certs must be the server certificate file itself.
|
||||
ssl_sock = ssl.wrap_socket(s, ca_certs=ca.ca_cert_path(),
|
||||
cert_reqs=ssl.CERT_REQUIRED)
|
||||
# Connect to the rabbitmq server using ssl.
|
||||
ssl_sock.connect((rabbit_host, ssl_port))
|
||||
# Get the certificate.
|
||||
certificate = ssl_sock.getpeercert()
|
||||
# SSL scoket connected and got the certificate, this passes the ssl test!
|
||||
print('Connected to the rabbitmq-server {0}:{1} using ssl!'.format(
|
||||
rabbit_host, ssl_port))
|
||||
except Exception as e:
|
||||
message = 'Failed to create an ssl connection to {0}:{1}\n{2}'.format(
|
||||
rabbit_host, ssl_port, str(e))
|
||||
amulet.raise_status(amulet.FAIL, msg=message)
|
||||
finally:
|
||||
ssl_sock.close()
|
||||
|
||||
print('The rabbitmq-server passed the configuration tests.')
|
|
@ -1,85 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
#
|
||||
# This Amulet test deploys rabbitmq-server
|
||||
#
|
||||
# Note: We use python2, because pika doesn't support python3
|
||||
|
||||
import amulet
|
||||
import pika
|
||||
import telnetlib
|
||||
|
||||
|
||||
# The number of seconds to wait for the environment to setup.
|
||||
seconds = 2700
|
||||
|
||||
d = amulet.Deployment(series="trusty")
|
||||
# Add the rabbitmq-server charm to the deployment.
|
||||
d.add('rabbitmq-server', units=2)
|
||||
|
||||
# Create a configuration.
|
||||
configuration = {'mirroring-queues': True,
|
||||
'management_plugin': True}
|
||||
d.configure('rabbitmq-server', configuration)
|
||||
d.expose('rabbitmq-server')
|
||||
|
||||
try:
|
||||
d.setup(timeout=seconds)
|
||||
d.sentry.wait(seconds)
|
||||
except amulet.helpers.TimeoutError:
|
||||
message = 'The environment did not setup in %d seconds.' % seconds
|
||||
amulet.raise_status(amulet.SKIP, msg=message)
|
||||
except:
|
||||
raise
|
||||
|
||||
|
||||
rabbit_unit = d.sentry.unit['rabbitmq-server/0']
|
||||
rabbit_unit2 = d.sentry.unit['rabbitmq-server/1']
|
||||
|
||||
commands = ['service rabbitmq-server status',
|
||||
'rabbitmqctl cluster_status']
|
||||
|
||||
for cmd in commands:
|
||||
output, code = rabbit_unit.run(cmd)
|
||||
message = cmd + ' | exit code: %d.' % code
|
||||
print(message)
|
||||
print(output)
|
||||
|
||||
if code != 0:
|
||||
amulet.raise_status(amulet.FAIL, msg=message)
|
||||
|
||||
rabbit_addr1 = rabbit_unit.info["public-address"]
|
||||
rabbit_port = "5672"
|
||||
rabbit_url = 'amqp://guest:guest@%s:%s/%%2F' % (rabbit_addr1, rabbit_port)
|
||||
|
||||
print('Connecting to %s' % rabbit_url)
|
||||
conn1 = pika.BlockingConnection(pika.connection.URLParameters(rabbit_url))
|
||||
channel = conn1.channel()
|
||||
print('Declaring queue')
|
||||
channel.queue_declare(queue='hello')
|
||||
orig_msg = 'Hello World!'
|
||||
print('Publishing message: %s' % orig_msg)
|
||||
channel.basic_publish(exchange='',
|
||||
routing_key='hello',
|
||||
body=orig_msg)
|
||||
|
||||
print('stopping rabbit in unit 0')
|
||||
rabbit_unit.run('service rabbitmq-server stop')
|
||||
|
||||
print('Consuming message from second unit')
|
||||
rabbit_addr2 = rabbit_unit2.info["public-address"]
|
||||
rabbit_url2 = 'amqp://guest:guest@%s:%s/%%2F' % (rabbit_addr2, rabbit_port)
|
||||
conn2 = pika.BlockingConnection(pika.connection.URLParameters(rabbit_url2))
|
||||
channel2 = conn2.channel()
|
||||
method_frame, header_frame, body = channel2.basic_get('hello')
|
||||
|
||||
if method_frame:
|
||||
print(method_frame, header_frame, body)
|
||||
assert body == orig_msg, '%s != %s' % (body, orig_msg)
|
||||
channel2.basic_ack(method_frame.delivery_tag)
|
||||
else:
|
||||
raise Exception('No message returned')
|
||||
|
||||
# check the management plugin is running
|
||||
mgmt_port = "15672"
|
||||
print('Checking management port')
|
||||
telnetlib.Telnet(rabbit_addr2, mgmt_port)
|
|
@ -1,71 +0,0 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
# This Amulet test performs a basic deploy and checks if rabbitmq is running.
|
||||
|
||||
import amulet
|
||||
import time
|
||||
|
||||
# The number of seconds to wait for the environment to setup.
|
||||
seconds = 900
|
||||
|
||||
# Create a dictionary for the rabbitmq configuration.
|
||||
rabbitmq_configuration = {
|
||||
'stats_cron_schedule': '*/1 * * * *'
|
||||
}
|
||||
d = amulet.Deployment(series='trusty')
|
||||
# Add the rabbitmq-server charm to the deployment.
|
||||
d.add('rabbitmq-server')
|
||||
# Configure options on the rabbitmq-server.
|
||||
d.configure('rabbitmq-server', rabbitmq_configuration)
|
||||
# Expose the server so we can connect.
|
||||
d.expose('rabbitmq-server')
|
||||
# XXX Remove charm= once this branch lands in the charm store
|
||||
d.add('nrpe-external-master',
|
||||
charm='lp:~gnuoy/charms/trusty/nrpe/services-rewrite')
|
||||
d.relate('rabbitmq-server:nrpe-external-master',
|
||||
'nrpe-external-master:nrpe-external-master')
|
||||
|
||||
try:
|
||||
# Execute the deployer with the current mapping.
|
||||
d.setup(timeout=seconds)
|
||||
except amulet.helpers.TimeoutError:
|
||||
message = 'The environment did not setup in %d seconds.' % seconds
|
||||
# The SKIP status enables skip or fail the test based on configuration.
|
||||
amulet.raise_status(amulet.SKIP, msg=message)
|
||||
except:
|
||||
raise
|
||||
print('The rabbitmq-server has been successfully deployed and related '
|
||||
'to nrpe-external-master.')
|
||||
|
||||
###############################################################################
|
||||
# # Verify nagios checks
|
||||
###############################################################################
|
||||
rabbitmq_sentry = d.sentry.unit['rabbitmq-server/0']
|
||||
|
||||
command = 'bash -c "$(egrep -oh /usr/local.* ' \
|
||||
'/etc/nagios/nrpe.d/check_rabbitmq.cfg)"'
|
||||
print(command)
|
||||
output, code = rabbitmq_sentry.run(command)
|
||||
print(output)
|
||||
if (code != 0):
|
||||
message = 'The ' + command + ' did not return the expected code of 0.'
|
||||
amulet.raise_status(amulet.FAIL, msg=message)
|
||||
else:
|
||||
print('The rabbitmq-server check_rabbitmq is OK')
|
||||
|
||||
print('Sleeping 70 seconds to make sure the monitoring cron has run')
|
||||
time.sleep(70)
|
||||
|
||||
command = 'bash -c "$(egrep -oh /usr/local.* ' \
|
||||
'/etc/nagios/nrpe.d/check_rabbitmq_queue.cfg)"'
|
||||
print(command)
|
||||
output, code = rabbitmq_sentry.run(command)
|
||||
print(output)
|
||||
if (code != 0):
|
||||
message = 'The ' + command + ' did not return the expected code of 0.'
|
||||
amulet.raise_status(amulet.FAIL, msg=message)
|
||||
else:
|
||||
print('The rabbitmq-server check_rabbitmq_queue is OK')
|
||||
|
||||
# Success!
|
||||
print('The rabbitmq-server passed the monitoring tests!')
|
|
@ -1,65 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
# This class uses Python to make AMQP calls to send and receive messages.
|
||||
# To send an AMQP message call this module with a host, port, and message.
|
||||
# To receive an AMQP message call this module with a host and port only.
|
||||
|
||||
import logging
|
||||
import pika
|
||||
import sys
|
||||
|
||||
|
||||
def send(host, port, message, queue='test'):
|
||||
""" Send an AMQP message to a host and port."""
|
||||
connection = None
|
||||
try:
|
||||
parameters = pika.ConnectionParameters(host, port)
|
||||
connection = pika.BlockingConnection(parameters)
|
||||
|
||||
channel = connection.channel()
|
||||
channel.queue_declare(queue)
|
||||
channel.basic_publish(exchange='', routing_key=queue, body=message)
|
||||
print('Message published to {0}:{1}'.format(host, port))
|
||||
except Exception as e:
|
||||
print('Unable to send message to {0}:{1}'.format(host, port))
|
||||
print(e)
|
||||
finally:
|
||||
if connection:
|
||||
connection.close()
|
||||
|
||||
|
||||
def callback(ch, method, properties, body):
|
||||
""" Handle the callback when the channel receives a message. """
|
||||
print(body)
|
||||
|
||||
|
||||
def receive(host, port, queue='test'):
|
||||
""" Connects to host and port, and consumes AMQP messages. """
|
||||
connection = None
|
||||
try:
|
||||
parameters = pika.ConnectionParameters(host, port)
|
||||
connection = pika.BlockingConnection(parameters)
|
||||
channel = connection.channel()
|
||||
channel.queue_declare(queue)
|
||||
channel.basic_consume(callback, queue, no_ack=True)
|
||||
except Exception as e:
|
||||
print('Unable to receive message from {0}:{1}'.format(host, port))
|
||||
print(e)
|
||||
finally:
|
||||
if connection:
|
||||
connection.close()
|
||||
|
||||
# Needed to disable pika complaining about logging levels not set.
|
||||
logging.basicConfig(level=logging.ERROR)
|
||||
|
||||
if len(sys.argv) == 3:
|
||||
host = sys.argv[1]
|
||||
port = int(sys.argv[2])
|
||||
receive(host, port)
|
||||
elif len(sys.argv) > 3:
|
||||
host = sys.argv[1]
|
||||
port = int(sys.argv[2])
|
||||
message = ' '.join(sys.argv[3:])
|
||||
send(host, port, message)
|
||||
else:
|
||||
print('Not enough arguments, host and port are required.')
|
|
@ -1,52 +0,0 @@
|
|||
# Copyright 2015 Canonical Limited.
|
||||
# This file provides common functions for amulet tests for the rabbitmq-server
|
||||
# juju charm.
|
||||
|
||||
import os
|
||||
from charmhelpers.contrib.ssl.service import ServiceCA
|
||||
|
||||
|
||||
class CA(object):
|
||||
"""
|
||||
Represents the certificate authority for use in RabbitMQ amulet tests.
|
||||
"""
|
||||
# The name of the rabbit certificate authority.
|
||||
CA_NAME = 'rabbit-server-ca'
|
||||
|
||||
# Put the certificate authority in a temporary location since
|
||||
# it is rebuilt for each amulet run.
|
||||
CA_PATH = '/tmp/rabbit-server-ca'
|
||||
|
||||
# The common name for the certificate itself.
|
||||
COMMON_NAME = 'rabbitmq-server'
|
||||
|
||||
def __init__(self):
|
||||
self.ca = ServiceCA(self.CA_NAME, self.CA_PATH)
|
||||
self.ca.init()
|
||||
self.ca.get_or_create_cert(self.COMMON_NAME)
|
||||
|
||||
def _load_file(self, path):
|
||||
contents = None
|
||||
with open(path) as f:
|
||||
contents = f.read()
|
||||
return contents
|
||||
|
||||
def get_key(self):
|
||||
"""
|
||||
Returns the contents of the rabbitmq private key.
|
||||
"""
|
||||
key_path = os.path.join(self.CA_PATH, 'certs', 'rabbitmq-server.key')
|
||||
return self._load_file(key_path)
|
||||
|
||||
def get_cert(self):
|
||||
"""
|
||||
Returns the contents of the rabbitmq certificate.
|
||||
"""
|
||||
cert_path = os.path.join(self.CA_PATH, 'certs', 'rabbitmq-server.crt')
|
||||
return self._load_file(cert_path)
|
||||
|
||||
def ca_cert_path(self):
|
||||
"""
|
||||
Returns the certificate authority certificate path.
|
||||
"""
|
||||
return os.path.join(self.CA_PATH, 'cacert.pem')
|
|
@ -1,17 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -ex
|
||||
|
||||
sudo add-apt-repository --yes ppa:juju/stable
|
||||
sudo apt-get update --yes
|
||||
sudo apt-get install --yes amulet \
|
||||
distro-info-data \
|
||||
python-cinderclient \
|
||||
python-distro-info \
|
||||
python-glanceclient \
|
||||
python-heatclient \
|
||||
python-keystoneclient \
|
||||
python-neutronclient \
|
||||
python-novaclient \
|
||||
python-pika \
|
||||
python-swiftclient
|
|
@ -1,21 +1,17 @@
|
|||
bootstrap: true
|
||||
reset: false
|
||||
virtualenv: true
|
||||
makefile:
|
||||
- lint
|
||||
- test
|
||||
sources:
|
||||
- ppa:juju/stable
|
||||
packages:
|
||||
- amulet
|
||||
- distro-info-data
|
||||
- python-ceilometerclient
|
||||
- python-cinderclient
|
||||
- python-distro-info
|
||||
- python-glanceclient
|
||||
- python-heatclient
|
||||
- python-keystoneclient
|
||||
- python-neutronclient
|
||||
- python-novaclient
|
||||
- python-pika
|
||||
- python-swiftclient
|
||||
# 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:
|
||||
|
|
46
tox.ini
46
tox.ini
|
@ -5,6 +5,8 @@ skipsdist = True
|
|||
[testenv]
|
||||
setenv = VIRTUAL_ENV={envdir}
|
||||
PYTHONHASHSEED=0
|
||||
AMULET_SETUP_TIMEOUT=2700
|
||||
passenv = AMULET_* HOME TERM
|
||||
install_command =
|
||||
pip install --allow-unverified python-apt {opts} {packages}
|
||||
commands = ostestr {posargs}
|
||||
|
@ -24,6 +26,50 @@ commands = flake8 {posargs} hooks unit_tests tests
|
|||
[testenv:venv]
|
||||
commands = {posargs}
|
||||
|
||||
[testenv:func27-noop]
|
||||
# DRY RUN - For Debug
|
||||
basepython = python2.7
|
||||
deps = -r{toxinidir}/requirements.txt
|
||||
-r{toxinidir}/test-requirements.txt
|
||||
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
|
||||
deps = -r{toxinidir}/requirements.txt
|
||||
-r{toxinidir}/test-requirements.txt
|
||||
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
|
||||
deps = -r{toxinidir}/requirements.txt
|
||||
-r{toxinidir}/test-requirements.txt
|
||||
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
|
||||
deps = -r{toxinidir}/requirements.txt
|
||||
-r{toxinidir}/test-requirements.txt
|
||||
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
|
||||
deps = -r{toxinidir}/requirements.txt
|
||||
-r{toxinidir}/test-requirements.txt
|
||||
commands =
|
||||
bundletester -vl DEBUG -r json -o func-results.json --test-pattern "dev-*" --no-destroy
|
||||
|
||||
[flake8]
|
||||
ignore = E402,E226
|
||||
exclude = hooks/charmhelpers
|
||||
|
|
Loading…
Reference in New Issue