update tests

This commit is contained in:
Ryan Beisner
2015-06-30 20:43:41 +00:00
parent 7d62f8ff26
commit d22a627adb
10 changed files with 336 additions and 330 deletions

View File

@@ -2,16 +2,18 @@
PYTHON := /usr/bin/env python
lint:
@echo "Running flake8 tests: "
@flake8 --exclude hooks/charmhelpers actions hooks unit_tests tests
@echo "OK"
@echo "Running charm proof: "
@flake8 --exclude hooks/charmhelpers,tests/charmhelpers \
actions hooks unit_tests tests
@charm proof
@echo "OK"
unit_test:
test:
@# Bundletester expects unit tests here.
@$(PYTHON) /usr/bin/nosetests --nologcapture --with-coverage unit_tests
functional_test:
@echo Starting Amulet tests...
@juju test -v -p AMULET_HTTP_PROXY,AMULET_OS_VIP --timeout 2700
bin/charm_helpers_sync.py:
@mkdir -p bin
@bzr cat lp:charm-helpers/tools/charm_helpers_sync/charm_helpers_sync.py \
@@ -21,15 +23,8 @@ sync: bin/charm_helpers_sync.py
@$(PYTHON) bin/charm_helpers_sync.py -c charm-helpers-hooks.yaml
@$(PYTHON) bin/charm_helpers_sync.py -c charm-helpers-tests.yaml
test:
@echo Starting Amulet tests...
# /!\ Note: The -v should only be temporary until Amulet sends
# raise_status() messages to stderr:
# https://bugs.launchpad.net/amulet/+bug/1320357
@juju test -v -p AMULET_HTTP_PROXY,AMULET_OS_VIP --timeout 2700
publish: lint unit_test
publish: lint test
bzr push lp:charms/glance
bzr push lp:charms/trusty/glance
all: unit_test lint
all: test lint

View File

@@ -6,7 +6,7 @@ description: |
(Parallax) and an image delivery service (Teller). These services are used
in conjunction by Nova to deliver images from object stores, such as
OpenStack's Swift service, to Nova's compute nodes.
categories:
tags:
- miscellaneous
provides:
nrpe-external-master:

View File

@@ -5,6 +5,10 @@ set -ex
sudo add-apt-repository --yes ppa:juju/stable
sudo apt-get update --yes
sudo apt-get install --yes python-amulet \
python-keystoneclient \
python-cinderclient \
python-distro-info \
python-glanceclient \
python-heatclient \
python-keystoneclient \
python-novaclient
python-swiftclient

0
tests/017-basic-trusty-kilo Normal file → Executable file
View File

0
tests/019-basic-vivid-kilo Normal file → Executable file
View File

View File

@@ -0,0 +1,11 @@
#!/usr/bin/python
"""Amulet tests on a basic glance deployment on trusty-liberty."""
from basic_deployment import GlanceBasicDeployment
if __name__ == '__main__':
deployment = GlanceBasicDeployment(series='trusty',
openstack='cloud:trusty-liberty',
source='cloud:trusty-updates/liberty')
deployment.run_tests()

View File

@@ -0,0 +1,9 @@
#!/usr/bin/python
"""Amulet tests on a basic glance deployment on wily-liberty."""
from basic_deployment import GlanceBasicDeployment
if __name__ == '__main__':
deployment = GlanceBasicDeployment(series='wily')
deployment.run_tests()

View File

@@ -1,6 +1,15 @@
This directory provides Amulet tests that focus on verification of Glance
deployments.
test_* methods are called in lexical sort order.
Test name convention to ensure desired test order:
1xx service and endpoint checks
2xx relation checks
3xx config checks
4xx functional checks
9xx restarts and other final checks
In order to run tests, you'll need charm-tools installed (in addition to
juju, of course):
sudo add-apt-repository ppa:juju/stable

View File

@@ -2,6 +2,7 @@
import amulet
import os
import time
import yaml
from charmhelpers.contrib.openstack.amulet.deployment import (
@@ -10,25 +11,24 @@ from charmhelpers.contrib.openstack.amulet.deployment import (
from charmhelpers.contrib.openstack.amulet.utils import (
OpenStackAmuletUtils,
DEBUG, # flake8: noqa
ERROR
DEBUG,
# ERROR
)
# Use DEBUG to turn on debug logging
u = OpenStackAmuletUtils(DEBUG)
class GlanceBasicDeployment(OpenStackAmuletDeployment):
'''Amulet tests on a basic file-backed glance deployment. Verify relations,
service status, endpoint service catalog, create and delete new image.'''
# TO-DO(beisner):
# * Add tests with different storage back ends
# * Resolve Essex->Havana juju set charm bug
class GlanceBasicDeployment(OpenStackAmuletDeployment):
"""Amulet tests on a basic file-backed glance deployment. Verify
relations, service status, endpoint service catalog, create and
delete new image."""
def __init__(self, series=None, openstack=None, source=None, git=False,
stable=False):
'''Deploy the entire test environment.'''
super(GlanceBasicDeployment, self).__init__(series, openstack, source, stable)
"""Deploy the entire test environment."""
super(GlanceBasicDeployment, self).__init__(series, openstack,
source, stable)
self.git = git
self._add_services()
self._add_relations()
@@ -37,20 +37,21 @@ class GlanceBasicDeployment(OpenStackAmuletDeployment):
self._initialize_tests()
def _add_services(self):
'''Add services
"""Add services
Add the services that we're testing, where glance 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': 'glance'}
other_services = [{'name': 'mysql'}, {'name': 'rabbitmq-server'},
other_services = [{'name': 'mysql'},
{'name': 'rabbitmq-server'},
{'name': 'keystone'}]
super(GlanceBasicDeployment, self)._add_services(this_service,
other_services)
def _add_relations(self):
'''Add relations for the services.'''
"""Add relations for the services."""
relations = {'glance:identity-service': 'keystone:identity-service',
'glance:shared-db': 'mysql:shared-db',
'keystone:shared-db': 'mysql:shared-db',
@@ -58,7 +59,7 @@ class GlanceBasicDeployment(OpenStackAmuletDeployment):
super(GlanceBasicDeployment, self)._add_relations(relations)
def _configure_services(self):
'''Configure all of the services.'''
"""Configure all of the services."""
glance_config = {}
if self.git:
branch = 'stable/' + self._get_openstack_release_string()
@@ -76,7 +77,8 @@ class GlanceBasicDeployment(OpenStackAmuletDeployment):
'http_proxy': amulet_http_proxy,
'https_proxy': amulet_http_proxy,
}
glance_config['openstack-origin-git'] = yaml.dump(openstack_origin_git)
glance_config['openstack-origin-git'] = \
yaml.dump(openstack_origin_git)
keystone_config = {'admin-password': 'openstack',
'admin-token': 'ubuntutesting'}
@@ -87,12 +89,19 @@ class GlanceBasicDeployment(OpenStackAmuletDeployment):
super(GlanceBasicDeployment, self)._configure_services(configs)
def _initialize_tests(self):
'''Perform final initialization before tests get run.'''
"""Perform final initialization before tests get run."""
# Access the sentries for inspecting service units
self.mysql_sentry = self.d.sentry.unit['mysql/0']
self.glance_sentry = self.d.sentry.unit['glance/0']
self.keystone_sentry = self.d.sentry.unit['keystone/0']
self.rabbitmq_sentry = self.d.sentry.unit['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()))
# Let things settle a bit before moving forward
time.sleep(30)
# Authenticate admin with keystone
self.keystone = u.authenticate_keystone_admin(self.keystone_sentry,
@@ -103,46 +112,103 @@ class GlanceBasicDeployment(OpenStackAmuletDeployment):
# Authenticate admin with glance endpoint
self.glance = u.authenticate_glance_admin(self.keystone)
u.log.debug('openstack release: {}'.format(self._get_openstack_release()))
def test_services(self):
'''Verify that the expected services are running on the
corresponding service units.'''
commands = {
self.mysql_sentry: ['status mysql'],
self.keystone_sentry: ['status keystone'],
self.glance_sentry: ['status glance-api', 'status glance-registry'],
self.rabbitmq_sentry: ['sudo service rabbitmq-server status']
def test_100_services(self):
"""Verify that the expected services are running on the
corresponding service units."""
services = {
self.mysql_sentry: ['mysql'],
self.keystone_sentry: ['keystone'],
self.glance_sentry: ['glance-api', 'glance-registry'],
self.rabbitmq_sentry: ['rabbitmq-server']
}
u.log.debug('commands: {}'.format(commands))
ret = u.validate_services(commands)
ret = u.validate_services_by_name(services)
if ret:
amulet.raise_status(amulet.FAIL, msg=ret)
def test_service_catalog(self):
'''Verify that the service catalog endpoint data'''
endpoint_vol = {'adminURL': u.valid_url,
'region': 'RegionOne',
'publicURL': u.valid_url,
'internalURL': u.valid_url}
endpoint_id = {'adminURL': u.valid_url,
'region': 'RegionOne',
'publicURL': u.valid_url,
'internalURL': u.valid_url}
if self._get_openstack_release() >= self.trusty_icehouse:
endpoint_vol['id'] = u.not_null
endpoint_id['id'] = u.not_null
expected = {'image': [endpoint_id],
'identity': [endpoint_id]}
def test_102_service_catalog(self):
"""Verify that the service catalog endpoint data is valid."""
u.log.debug('Checking keystone service catalog...')
endpoint_check = {
'adminURL': u.valid_url,
'id': u.not_null,
'region': 'RegionOne',
'publicURL': u.valid_url,
'internalURL': u.valid_url
}
expected = {
'image': [endpoint_check],
'identity': [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)
def test_mysql_glance_db_relation(self):
'''Verify the mysql:glance shared-db relation data'''
def test_104_glance_endpoint(self):
"""Verify the glance endpoint data."""
u.log.debug('Checking glance api endpoint data...')
endpoints = self.keystone.endpoints.list()
admin_port = internal_port = public_port = '9292'
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:
amulet.raise_status(amulet.FAIL,
msg='glance endpoint: {}'.format(ret))
def test_106_keystone_endpoint(self):
"""Verify the keystone endpoint data."""
u.log.debug('Checking keystone api endpoint data...')
endpoints = self.keystone.endpoints.list()
admin_port = '35357'
internal_port = public_port = '5000'
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:
amulet.raise_status(amulet.FAIL,
msg='keystone endpoint: {}'.format(ret))
def test_110_users(self):
"""Verify expected users."""
u.log.debug('Checking keystone users...')
expected = [
{'name': 'glance',
'enabled': True,
'tenantId': u.not_null,
'id': u.not_null,
'email': 'juju@localhost'},
{'name': 'admin',
'enabled': True,
'tenantId': u.not_null,
'id': u.not_null,
'email': 'juju@localhost'}
]
actual = self.keystone.users.list()
ret = u.validate_user_data(expected, actual)
if ret:
amulet.raise_status(amulet.FAIL, msg=ret)
def test_200_mysql_glance_db_relation(self):
"""Verify the mysql:glance shared-db relation data"""
u.log.debug('Checking mysql to glance shared-db relation data...')
unit = self.mysql_sentry
relation = ['shared-db', 'glance:shared-db']
expected = {
@@ -154,8 +220,9 @@ class GlanceBasicDeployment(OpenStackAmuletDeployment):
message = u.relation_error('mysql shared-db', ret)
amulet.raise_status(amulet.FAIL, msg=message)
def test_glance_mysql_db_relation(self):
'''Verify the glance:mysql shared-db relation data'''
def test_201_glance_mysql_db_relation(self):
"""Verify the glance:mysql shared-db relation data"""
u.log.debug('Checking glance to mysql shared-db relation data...')
unit = self.glance_sentry
relation = ['shared-db', 'mysql:shared-db']
expected = {
@@ -169,8 +236,9 @@ class GlanceBasicDeployment(OpenStackAmuletDeployment):
message = u.relation_error('glance shared-db', ret)
amulet.raise_status(amulet.FAIL, msg=message)
def test_keystone_glance_id_relation(self):
'''Verify the keystone:glance identity-service relation data'''
def test_202_keystone_glance_id_relation(self):
"""Verify the keystone:glance identity-service relation data"""
u.log.debug('Checking keystone to glance id relation data...')
unit = self.keystone_sentry
relation = ['identity-service',
'glance:identity-service']
@@ -193,8 +261,9 @@ class GlanceBasicDeployment(OpenStackAmuletDeployment):
message = u.relation_error('keystone identity-service', ret)
amulet.raise_status(amulet.FAIL, msg=message)
def test_glance_keystone_id_relation(self):
'''Verify the glance:keystone identity-service relation data'''
def test_203_glance_keystone_id_relation(self):
"""Verify the glance:keystone identity-service relation data"""
u.log.debug('Checking glance to keystone relation data...')
unit = self.glance_sentry
relation = ['identity-service',
'keystone:identity-service']
@@ -211,8 +280,9 @@ class GlanceBasicDeployment(OpenStackAmuletDeployment):
message = u.relation_error('glance identity-service', ret)
amulet.raise_status(amulet.FAIL, msg=message)
def test_rabbitmq_glance_amqp_relation(self):
'''Verify the rabbitmq-server:glance amqp relation data'''
def test_204_rabbitmq_glance_amqp_relation(self):
"""Verify the rabbitmq-server:glance amqp relation data"""
u.log.debug('Checking rmq to glance amqp relation data...')
unit = self.rabbitmq_sentry
relation = ['amqp', 'glance:amqp']
expected = {
@@ -225,8 +295,9 @@ class GlanceBasicDeployment(OpenStackAmuletDeployment):
message = u.relation_error('rabbitmq amqp', ret)
amulet.raise_status(amulet.FAIL, msg=message)
def test_glance_rabbitmq_amqp_relation(self):
'''Verify the glance:rabbitmq-server amqp relation data'''
def test_205_glance_rabbitmq_amqp_relation(self):
"""Verify the glance:rabbitmq-server amqp relation data"""
u.log.debug('Checking glance to rmq amqp relation data...')
unit = self.glance_sentry
relation = ['amqp', 'rabbitmq-server:amqp']
expected = {
@@ -239,291 +310,180 @@ class GlanceBasicDeployment(OpenStackAmuletDeployment):
message = u.relation_error('glance amqp', ret)
amulet.raise_status(amulet.FAIL, msg=message)
def test_image_create_delete(self):
'''Create new cirros image in glance, verify, then delete it'''
# Create a new image
image_name = 'cirros-image-1'
image_new = u.create_cirros_image(self.glance, image_name)
# Confirm image is created and has status of 'active'
if not image_new:
message = 'glance image create failed'
amulet.raise_status(amulet.FAIL, msg=message)
# Verify new image name
images_list = list(self.glance.images.list())
if images_list[0].name != image_name:
message = 'glance image create failed or unexpected image name {}'.format(images_list[0].name)
amulet.raise_status(amulet.FAIL, msg=message)
# Delete the new image
u.log.debug('image count before delete: {}'.format(len(list(self.glance.images.list()))))
u.delete_image(self.glance, image_new)
u.log.debug('image count after delete: {}'.format(len(list(self.glance.images.list()))))
def test_glance_api_default_config(self):
'''Verify default section configs in glance-api.conf and
compare some of the parameters to relation data.'''
def test_300_glance_api_default_config(self):
"""Verify default section configs in glance-api.conf and
compare some of the parameters to relation data."""
u.log.debug('Checking glance api config file...')
unit = self.glance_sentry
unit_ks = self.keystone_sentry
rel_gl_mq = unit.relation('amqp', 'rabbitmq-server:amqp')
rel_ks_gl = unit_ks.relation('identity-service',
'glance:identity-service')
rel_my_gl = self.mysql_sentry.relation('shared-db', 'glance:shared-db')
db_uri = "mysql://{}:{}@{}/{}".format('glance', rel_my_gl['password'],
rel_my_gl['db_host'], 'glance')
conf = '/etc/glance/glance-api.conf'
expected = {'use_syslog': 'False',
'default_store': 'file',
'filesystem_store_datadir': '/var/lib/glance/images/',
'rabbit_userid': rel_gl_mq['username'],
'log_file': '/var/log/glance/api.log',
'debug': 'False',
'verbose': 'False'}
section = 'DEFAULT'
expected = {
'DEFAULT': {
'debug': 'False',
'verbose': 'False',
'use_syslog': 'False',
'log_file': '/var/log/glance/api.log',
'default_store': 'file',
'filesystem_store_datadir': '/var/lib/glance/images/',
'rabbit_userid': rel_gl_mq['username'],
'bind_host': '0.0.0.0',
'bind_port': '9282',
'registry_host': '0.0.0.0',
'registry_port': '9191',
'registry_client_protocol': 'http',
'delayed_delete': 'False',
'scrub_time': '43200',
'notification_driver': 'rabbit',
'filesystem_store_datadir': '/var/lib/glance/images/',
'scrubber_datadir': '/var/lib/glance/scrubber',
'image_cache_dir': '/var/lib/glance/image-cache/',
'db_enforce_mysql_charset': 'False',
'rabbit_userid': 'glance',
'rabbit_virtual_host': 'openstack',
'rabbit_password': u.not_null,
'rabbit_host': u.valid_ip
},
'keystone_authtoken': {
'admin_user': 'glance',
'admin_password': rel_ks_gl['service_password'],
'auth_uri': u.valid_url,
'auth_host': u.valid_ip,
'auth_port': '35357',
'auth_protocol': 'http',
},
'database': {
'connection': db_uri,
'sql_idle_timeout': '3600'
}
}
if self._get_openstack_release() <= self.precise_havana:
# Defaults were different before icehouse
expected['debug'] = 'True'
expected['verbose'] = 'True'
ret = u.validate_config_data(unit, conf, section, expected)
if ret:
message = "glance-api default config error: {}".format(ret)
amulet.raise_status(amulet.FAIL, msg=message)
def test_glance_api_auth_config(self):
'''Verify authtoken section config in glance-api.conf using
glance/keystone relation data.'''
unit_gl = self.glance_sentry
unit_ks = self.keystone_sentry
rel_gl_mq = unit_gl.relation('amqp', 'rabbitmq-server:amqp')
rel_ks_gl = unit_ks.relation('identity-service', 'glance:identity-service')
conf = '/etc/glance/glance-api.conf'
section = 'keystone_authtoken'
if self._get_openstack_release() > self.precise_havana:
# No auth config exists in this file before icehouse
expected = {'admin_user': 'glance',
'admin_password': rel_ks_gl['service_password']}
ret = u.validate_config_data(unit_gl, conf, section, expected)
for section, pairs in expected.iteritems():
ret = u.validate_config_data(unit, conf, section, pairs)
if ret:
message = "glance-api auth config error: {}".format(ret)
message = "glance api config error: {}".format(ret)
amulet.raise_status(amulet.FAIL, msg=message)
def test_glance_api_paste_auth_config(self):
'''Verify authtoken section config in glance-api-paste.ini using
glance/keystone relation data.'''
unit_gl = self.glance_sentry
unit_ks = self.keystone_sentry
rel_gl_mq = unit_gl.relation('amqp', 'rabbitmq-server:amqp')
rel_ks_gl = unit_ks.relation('identity-service', 'glance:identity-service')
def _get_filter_factory_expected_dict(self):
"""Return expected authtoken filter factory dict for OS release"""
if self._get_openstack_release() < self.vivid_kilo:
# Juno and earlier
val = 'keystoneclient.middleware.auth_token:filter_factory'
else:
# Kilo and later
val = 'keystonemiddleware.auth_token: filter_factory'
return {'filter:authtoken': {'paste.filter_factory': val}}
def test_304_glance_api_paste_auth_config(self):
"""Verify authtoken section config in glance-api-paste.ini using
glance/keystone relation data."""
u.log.debug('Checking glance api paste config file...')
unit = self.glance_sentry
conf = '/etc/glance/glance-api-paste.ini'
section = 'filter:authtoken'
expected = self._get_filter_factory_expected_dict()
if self._get_openstack_release() <= self.precise_havana:
# No auth config exists in this file after havana
expected = {'admin_user': 'glance',
'admin_password': rel_ks_gl['service_password']}
ret = u.validate_config_data(unit_gl, conf, section, expected)
for section, pairs in expected.iteritems():
ret = u.validate_config_data(unit, conf, section, pairs)
if ret:
message = "glance-api-paste auth config error: {}".format(ret)
message = "glance api paste config error: {}".format(ret)
amulet.raise_status(amulet.FAIL, msg=message)
def test_glance_registry_paste_auth_config(self):
'''Verify authtoken section config in glance-registry-paste.ini using
glance/keystone relation data.'''
unit_gl = self.glance_sentry
unit_ks = self.keystone_sentry
rel_gl_mq = unit_gl.relation('amqp', 'rabbitmq-server:amqp')
rel_ks_gl = unit_ks.relation('identity-service', 'glance:identity-service')
def test_306_glance_registry_paste_auth_config(self):
"""Verify authtoken section config in glance-registry-paste.ini using
glance/keystone relation data."""
u.log.debug('Checking glance registry paste config file...')
unit = self.glance_sentry
conf = '/etc/glance/glance-registry-paste.ini'
section = 'filter:authtoken'
expected = self._get_filter_factory_expected_dict()
if self._get_openstack_release() <= self.precise_havana:
# No auth config exists in this file after havana
expected = {'admin_user': 'glance',
'admin_password': rel_ks_gl['service_password']}
ret = u.validate_config_data(unit_gl, conf, section, expected)
for section, pairs in expected.iteritems():
ret = u.validate_config_data(unit, conf, section, pairs)
if ret:
message = "glance-registry-paste auth config error: {}".format(ret)
message = "glance registry paste config error: {}".format(ret)
amulet.raise_status(amulet.FAIL, msg=message)
def test_glance_registry_default_config(self):
'''Verify default section configs in glance-registry.conf'''
def test_308_glance_registry_default_config(self):
"""Verify configs in glance-registry.conf"""
u.log.debug('Checking glance registry config file...')
unit = self.glance_sentry
conf = '/etc/glance/glance-registry.conf'
expected = {'use_syslog': 'False',
'log_file': '/var/log/glance/registry.log',
'debug': 'False',
'verbose': 'False'}
section = 'DEFAULT'
if self._get_openstack_release() <= self.precise_havana:
# Defaults were different before icehouse
expected['debug'] = 'True'
expected['verbose'] = 'True'
ret = u.validate_config_data(unit, conf, section, expected)
if ret:
message = "glance-registry default config error: {}".format(ret)
amulet.raise_status(amulet.FAIL, msg=message)
def test_glance_registry_auth_config(self):
'''Verify authtoken section config in glance-registry.conf
using glance/keystone relation data.'''
unit_gl = self.glance_sentry
unit_ks = self.keystone_sentry
rel_gl_mq = unit_gl.relation('amqp', 'rabbitmq-server:amqp')
rel_ks_gl = unit_ks.relation('identity-service', 'glance:identity-service')
rel_ks_gl = unit_ks.relation('identity-service',
'glance:identity-service')
rel_my_gl = self.mysql_sentry.relation('shared-db', 'glance:shared-db')
db_uri = "mysql://{}:{}@{}/{}".format('glance', rel_my_gl['password'],
rel_my_gl['db_host'], 'glance')
conf = '/etc/glance/glance-registry.conf'
section = 'keystone_authtoken'
if self._get_openstack_release() > self.precise_havana:
# No auth config exists in this file before icehouse
expected = {'admin_user': 'glance',
'admin_password': rel_ks_gl['service_password']}
expected = {
'DEFAULT': {
'use_syslog': 'False',
'log_file': '/var/log/glance/registry.log',
'debug': 'False',
'verbose': 'False',
'bind_host': '0.0.0.0',
'bind_port': '9191'
},
'database': {
'connection': db_uri,
'sql_idle_timeout': '3600'
},
'keystone_authtoken': {
'admin_user': 'glance',
'admin_password': rel_ks_gl['service_password'],
'auth_uri': u.valid_url,
'auth_host': u.valid_ip,
'auth_port': '35357',
'auth_protocol': 'http',
},
}
ret = u.validate_config_data(unit_gl, conf, section, expected)
for section, pairs in expected.iteritems():
ret = u.validate_config_data(unit, conf, section, pairs)
if ret:
message = "glance-registry keystone_authtoken config error: {}".format(ret)
message = "glance registry paste config error: {}".format(ret)
amulet.raise_status(amulet.FAIL, msg=message)
def test_glance_api_database_config(self):
'''Verify database config in glance-api.conf and
compare with a db uri constructed from relation data.'''
unit = self.glance_sentry
conf = '/etc/glance/glance-api.conf'
relation = self.mysql_sentry.relation('shared-db', 'glance:shared-db')
db_uri = "mysql://{}:{}@{}/{}".format('glance', relation['password'],
relation['db_host'], 'glance')
expected = {'connection': db_uri, 'sql_idle_timeout': '3600'}
section = 'database'
def test_410_glance_image_create_delete(self):
"""Create new cirros image in glance, verify, then delete it."""
u.log.debug('Creating, checking and deleting glance image...')
img_new = u.create_cirros_image(self.glance, "cirros-image-1")
img_id = img_new.id
u.delete_resource(self.glance.images, img_id, msg="glance image")
if self._get_openstack_release() <= self.precise_havana:
# Section and directive for this config changed in icehouse
expected = {'sql_connection': db_uri, 'sql_idle_timeout': '3600'}
section = 'DEFAULT'
def test_900_glance_restart_on_config_change(self):
"""Verify that the specified services are restarted when the config
is changed."""
sentry = self.glance_sentry
juju_service = 'glance'
ret = u.validate_config_data(unit, conf, section, expected)
if ret:
message = "glance db config error: {}".format(ret)
amulet.raise_status(amulet.FAIL, msg=message)
# Expected default and alternate values
set_default = {'use-syslog': 'False'}
set_alternate = {'use-syslog': 'True'}
def test_glance_registry_database_config(self):
'''Verify database config in glance-registry.conf and
compare with a db uri constructed from relation data.'''
unit = self.glance_sentry
conf = '/etc/glance/glance-registry.conf'
relation = self.mysql_sentry.relation('shared-db', 'glance:shared-db')
db_uri = "mysql://{}:{}@{}/{}".format('glance', relation['password'],
relation['db_host'], 'glance')
expected = {'connection': db_uri, 'sql_idle_timeout': '3600'}
section = 'database'
# Config file affected by juju set config change
conf_file = '/etc/glance/glance-api.conf'
if self._get_openstack_release() <= self.precise_havana:
# Section and directive for this config changed in icehouse
expected = {'sql_connection': db_uri, 'sql_idle_timeout': '3600'}
section = 'DEFAULT'
# Services which are expected to restart upon config change
services = ['glance-api', 'glance-registry']
ret = u.validate_config_data(unit, conf, section, expected)
if ret:
message = "glance db config error: {}".format(ret)
amulet.raise_status(amulet.FAIL, msg=message)
# Make config change, check for service restarts
u.log.debug('Making config change on {}...'.format(juju_service))
self.d.configure(juju_service, set_alternate)
def test_glance_endpoint(self):
'''Verify the glance endpoint data.'''
endpoints = self.keystone.endpoints.list()
admin_port = internal_port = public_port = '9292'
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)
sleep_time = 30
for s in services:
u.log.debug("Checking that service restarted: {}".format(s))
if not u.service_restarted(sentry, s,
conf_file, 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
if ret:
amulet.raise_status(amulet.FAIL,
msg='glance endpoint: {}'.format(ret))
def test_keystone_endpoint(self):
'''Verify the keystone endpoint data.'''
endpoints = self.keystone.endpoints.list()
admin_port = '35357'
internal_port = public_port = '5000'
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:
amulet.raise_status(amulet.FAIL,
msg='keystone endpoint: {}'.format(ret))
def _change_config(self):
if self._get_openstack_release() > self.precise_havana:
self.d.configure('glance', {'debug': 'True'})
else:
self.d.configure('glance', {'debug': 'False'})
def _restore_config(self):
if self._get_openstack_release() > self.precise_havana:
self.d.configure('glance', {'debug': 'False'})
else:
self.d.configure('glance', {'debug': 'True'})
def test_z_glance_restart_on_config_change(self):
'''Verify that glance is restarted when the config is changed.
Note(coreycb): The method name with the _z_ is a little odd
but it forces the test to run last. It just makes things
easier because restarting services requires re-authorization.
'''
if self._get_openstack_release() <= self.precise_havana:
# /!\ NOTE(beisner): Glance charm before Icehouse doesn't respond
# to attempted config changes via juju / juju set.
# https://bugs.launchpad.net/charms/+source/glance/+bug/1340307
u.log.error('NOTE(beisner): skipping glance restart on config ' +
'change check due to bug 1340307.')
return
# Make config change to trigger a service restart
self._change_config()
if not u.service_restarted(self.glance_sentry, 'glance-api',
'/etc/glance/glance-api.conf'):
self._restore_config()
message = "glance service didn't restart after config change"
amulet.raise_status(amulet.FAIL, msg=message)
if not u.service_restarted(self.glance_sentry, 'glance-registry',
'/etc/glance/glance-registry.conf',
sleep_time=0):
self._restore_config()
message = "glance service didn't restart after config change"
amulet.raise_status(amulet.FAIL, msg=message)
# Return to original config
self._restore_config()
def test_users(self):
'''Verify expected users.'''
user0 = {'name': 'glance',
'enabled': True,
'tenantId': u.not_null,
'id': u.not_null,
'email': 'juju@localhost'}
user1 = {'name': 'admin',
'enabled': True,
'tenantId': u.not_null,
'id': u.not_null,
'email': 'juju@localhost'}
expected = [user0, user1]
actual = self.keystone.users.list()
ret = u.validate_user_data(expected, actual)
if ret:
amulet.raise_status(amulet.FAIL, msg=ret)
self.d.configure(juju_service, set_default)

18
tests/tests.yaml Normal file
View File

@@ -0,0 +1,18 @@
bootstrap: true
reset: true
virtualenv: true
makefile:
- lint
- test
sources:
- ppa:juju/stable
packages:
- amulet
- python-amulet
- python-cinderclient
- python-distro-info
- python-glanceclient
- python-heatclient
- python-keystoneclient
- python-novaclient
- python-swiftclient