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 PYTHON := /usr/bin/env python
lint: lint:
@echo "Running flake8 tests: " @flake8 --exclude hooks/charmhelpers,tests/charmhelpers \
@flake8 --exclude hooks/charmhelpers actions hooks unit_tests tests actions hooks unit_tests tests
@echo "OK"
@echo "Running charm proof: "
@charm proof @charm proof
@echo "OK"
unit_test: test:
@# Bundletester expects unit tests here.
@$(PYTHON) /usr/bin/nosetests --nologcapture --with-coverage unit_tests @$(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: bin/charm_helpers_sync.py:
@mkdir -p bin @mkdir -p bin
@bzr cat lp:charm-helpers/tools/charm_helpers_sync/charm_helpers_sync.py \ @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-hooks.yaml
@$(PYTHON) bin/charm_helpers_sync.py -c charm-helpers-tests.yaml @$(PYTHON) bin/charm_helpers_sync.py -c charm-helpers-tests.yaml
test: publish: lint 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
bzr push lp:charms/glance bzr push lp:charms/glance
bzr push lp:charms/trusty/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 (Parallax) and an image delivery service (Teller). These services are used
in conjunction by Nova to deliver images from object stores, such as in conjunction by Nova to deliver images from object stores, such as
OpenStack's Swift service, to Nova's compute nodes. OpenStack's Swift service, to Nova's compute nodes.
categories: tags:
- miscellaneous - miscellaneous
provides: provides:
nrpe-external-master: nrpe-external-master:

View File

@@ -5,6 +5,10 @@ set -ex
sudo add-apt-repository --yes ppa:juju/stable sudo add-apt-repository --yes ppa:juju/stable
sudo apt-get update --yes sudo apt-get update --yes
sudo apt-get install --yes python-amulet \ sudo apt-get install --yes python-amulet \
python-keystoneclient \ python-cinderclient \
python-distro-info \
python-glanceclient \ python-glanceclient \
python-heatclient \
python-keystoneclient \
python-novaclient 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 This directory provides Amulet tests that focus on verification of Glance
deployments. 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 In order to run tests, you'll need charm-tools installed (in addition to
juju, of course): juju, of course):
sudo add-apt-repository ppa:juju/stable sudo add-apt-repository ppa:juju/stable

View File

@@ -2,6 +2,7 @@
import amulet import amulet
import os import os
import time
import yaml import yaml
from charmhelpers.contrib.openstack.amulet.deployment import ( 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 ( from charmhelpers.contrib.openstack.amulet.utils import (
OpenStackAmuletUtils, OpenStackAmuletUtils,
DEBUG, # flake8: noqa DEBUG,
ERROR # ERROR
) )
# Use DEBUG to turn on debug logging # Use DEBUG to turn on debug logging
u = OpenStackAmuletUtils(DEBUG) 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): class GlanceBasicDeployment(OpenStackAmuletDeployment):
# * Add tests with different storage back ends """Amulet tests on a basic file-backed glance deployment. Verify
# * Resolve Essex->Havana juju set charm bug relations, service status, endpoint service catalog, create and
delete new image."""
def __init__(self, series=None, openstack=None, source=None, git=False, def __init__(self, series=None, openstack=None, source=None, git=False,
stable=False): stable=False):
'''Deploy the entire test environment.''' """Deploy the entire test environment."""
super(GlanceBasicDeployment, self).__init__(series, openstack, source, stable) super(GlanceBasicDeployment, self).__init__(series, openstack,
source, stable)
self.git = git self.git = git
self._add_services() self._add_services()
self._add_relations() self._add_relations()
@@ -37,20 +37,21 @@ class GlanceBasicDeployment(OpenStackAmuletDeployment):
self._initialize_tests() self._initialize_tests()
def _add_services(self): def _add_services(self):
'''Add services """Add services
Add the services that we're testing, where glance is local, Add the services that we're testing, where glance is local,
and the rest of the service are from lp branches that are and the rest of the service are from lp branches that are
compatible with the local charm (e.g. stable or next). compatible with the local charm (e.g. stable or next).
''' """
this_service = {'name': 'glance'} this_service = {'name': 'glance'}
other_services = [{'name': 'mysql'}, {'name': 'rabbitmq-server'}, other_services = [{'name': 'mysql'},
{'name': 'rabbitmq-server'},
{'name': 'keystone'}] {'name': 'keystone'}]
super(GlanceBasicDeployment, self)._add_services(this_service, super(GlanceBasicDeployment, self)._add_services(this_service,
other_services) other_services)
def _add_relations(self): def _add_relations(self):
'''Add relations for the services.''' """Add relations for the services."""
relations = {'glance:identity-service': 'keystone:identity-service', relations = {'glance:identity-service': 'keystone:identity-service',
'glance:shared-db': 'mysql:shared-db', 'glance:shared-db': 'mysql:shared-db',
'keystone:shared-db': 'mysql:shared-db', 'keystone:shared-db': 'mysql:shared-db',
@@ -58,7 +59,7 @@ class GlanceBasicDeployment(OpenStackAmuletDeployment):
super(GlanceBasicDeployment, self)._add_relations(relations) super(GlanceBasicDeployment, self)._add_relations(relations)
def _configure_services(self): def _configure_services(self):
'''Configure all of the services.''' """Configure all of the services."""
glance_config = {} glance_config = {}
if self.git: if self.git:
branch = 'stable/' + self._get_openstack_release_string() branch = 'stable/' + self._get_openstack_release_string()
@@ -76,7 +77,8 @@ class GlanceBasicDeployment(OpenStackAmuletDeployment):
'http_proxy': amulet_http_proxy, 'http_proxy': amulet_http_proxy,
'https_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', keystone_config = {'admin-password': 'openstack',
'admin-token': 'ubuntutesting'} 'admin-token': 'ubuntutesting'}
@@ -87,12 +89,19 @@ class GlanceBasicDeployment(OpenStackAmuletDeployment):
super(GlanceBasicDeployment, self)._configure_services(configs) super(GlanceBasicDeployment, self)._configure_services(configs)
def _initialize_tests(self): 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 # Access the sentries for inspecting service units
self.mysql_sentry = self.d.sentry.unit['mysql/0'] self.mysql_sentry = self.d.sentry.unit['mysql/0']
self.glance_sentry = self.d.sentry.unit['glance/0'] self.glance_sentry = self.d.sentry.unit['glance/0']
self.keystone_sentry = self.d.sentry.unit['keystone/0'] self.keystone_sentry = self.d.sentry.unit['keystone/0']
self.rabbitmq_sentry = self.d.sentry.unit['rabbitmq-server/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 # Authenticate admin with keystone
self.keystone = u.authenticate_keystone_admin(self.keystone_sentry, self.keystone = u.authenticate_keystone_admin(self.keystone_sentry,
@@ -103,46 +112,103 @@ class GlanceBasicDeployment(OpenStackAmuletDeployment):
# Authenticate admin with glance endpoint # Authenticate admin with glance endpoint
self.glance = u.authenticate_glance_admin(self.keystone) self.glance = u.authenticate_glance_admin(self.keystone)
u.log.debug('openstack release: {}'.format(self._get_openstack_release())) def test_100_services(self):
"""Verify that the expected services are running on the
def test_services(self): corresponding service units."""
'''Verify that the expected services are running on the services = {
corresponding service units.''' self.mysql_sentry: ['mysql'],
commands = { self.keystone_sentry: ['keystone'],
self.mysql_sentry: ['status mysql'], self.glance_sentry: ['glance-api', 'glance-registry'],
self.keystone_sentry: ['status keystone'], self.rabbitmq_sentry: ['rabbitmq-server']
self.glance_sentry: ['status glance-api', 'status glance-registry'],
self.rabbitmq_sentry: ['sudo service rabbitmq-server status']
} }
u.log.debug('commands: {}'.format(commands))
ret = u.validate_services(commands) ret = u.validate_services_by_name(services)
if ret: if ret:
amulet.raise_status(amulet.FAIL, msg=ret) amulet.raise_status(amulet.FAIL, msg=ret)
def test_service_catalog(self): def test_102_service_catalog(self):
'''Verify that the service catalog endpoint data''' """Verify that the service catalog endpoint data is valid."""
endpoint_vol = {'adminURL': u.valid_url, u.log.debug('Checking keystone service catalog...')
endpoint_check = {
'adminURL': u.valid_url,
'id': u.not_null,
'region': 'RegionOne', 'region': 'RegionOne',
'publicURL': u.valid_url, 'publicURL': u.valid_url,
'internalURL': u.valid_url} 'internalURL': u.valid_url
endpoint_id = {'adminURL': u.valid_url, }
'region': 'RegionOne', expected = {
'publicURL': u.valid_url, 'image': [endpoint_check],
'internalURL': u.valid_url} 'identity': [endpoint_check]
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]}
actual = self.keystone.service_catalog.get_endpoints() actual = self.keystone.service_catalog.get_endpoints()
ret = u.validate_svc_catalog_endpoint_data(expected, actual) ret = u.validate_svc_catalog_endpoint_data(expected, actual)
if ret: if ret:
amulet.raise_status(amulet.FAIL, msg=ret) amulet.raise_status(amulet.FAIL, msg=ret)
def test_mysql_glance_db_relation(self): def test_104_glance_endpoint(self):
'''Verify the mysql:glance shared-db relation data''' """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 unit = self.mysql_sentry
relation = ['shared-db', 'glance:shared-db'] relation = ['shared-db', 'glance:shared-db']
expected = { expected = {
@@ -154,8 +220,9 @@ class GlanceBasicDeployment(OpenStackAmuletDeployment):
message = u.relation_error('mysql shared-db', ret) message = u.relation_error('mysql shared-db', ret)
amulet.raise_status(amulet.FAIL, msg=message) amulet.raise_status(amulet.FAIL, msg=message)
def test_glance_mysql_db_relation(self): def test_201_glance_mysql_db_relation(self):
'''Verify the glance:mysql shared-db relation data''' """Verify the glance:mysql shared-db relation data"""
u.log.debug('Checking glance to mysql shared-db relation data...')
unit = self.glance_sentry unit = self.glance_sentry
relation = ['shared-db', 'mysql:shared-db'] relation = ['shared-db', 'mysql:shared-db']
expected = { expected = {
@@ -169,8 +236,9 @@ class GlanceBasicDeployment(OpenStackAmuletDeployment):
message = u.relation_error('glance shared-db', ret) message = u.relation_error('glance shared-db', ret)
amulet.raise_status(amulet.FAIL, msg=message) amulet.raise_status(amulet.FAIL, msg=message)
def test_keystone_glance_id_relation(self): def test_202_keystone_glance_id_relation(self):
'''Verify the keystone:glance identity-service relation data''' """Verify the keystone:glance identity-service relation data"""
u.log.debug('Checking keystone to glance id relation data...')
unit = self.keystone_sentry unit = self.keystone_sentry
relation = ['identity-service', relation = ['identity-service',
'glance:identity-service'] 'glance:identity-service']
@@ -193,8 +261,9 @@ class GlanceBasicDeployment(OpenStackAmuletDeployment):
message = u.relation_error('keystone identity-service', ret) message = u.relation_error('keystone identity-service', ret)
amulet.raise_status(amulet.FAIL, msg=message) amulet.raise_status(amulet.FAIL, msg=message)
def test_glance_keystone_id_relation(self): def test_203_glance_keystone_id_relation(self):
'''Verify the glance:keystone identity-service relation data''' """Verify the glance:keystone identity-service relation data"""
u.log.debug('Checking glance to keystone relation data...')
unit = self.glance_sentry unit = self.glance_sentry
relation = ['identity-service', relation = ['identity-service',
'keystone:identity-service'] 'keystone:identity-service']
@@ -211,8 +280,9 @@ class GlanceBasicDeployment(OpenStackAmuletDeployment):
message = u.relation_error('glance identity-service', ret) message = u.relation_error('glance identity-service', ret)
amulet.raise_status(amulet.FAIL, msg=message) amulet.raise_status(amulet.FAIL, msg=message)
def test_rabbitmq_glance_amqp_relation(self): def test_204_rabbitmq_glance_amqp_relation(self):
'''Verify the rabbitmq-server:glance amqp relation data''' """Verify the rabbitmq-server:glance amqp relation data"""
u.log.debug('Checking rmq to glance amqp relation data...')
unit = self.rabbitmq_sentry unit = self.rabbitmq_sentry
relation = ['amqp', 'glance:amqp'] relation = ['amqp', 'glance:amqp']
expected = { expected = {
@@ -225,8 +295,9 @@ class GlanceBasicDeployment(OpenStackAmuletDeployment):
message = u.relation_error('rabbitmq amqp', ret) message = u.relation_error('rabbitmq amqp', ret)
amulet.raise_status(amulet.FAIL, msg=message) amulet.raise_status(amulet.FAIL, msg=message)
def test_glance_rabbitmq_amqp_relation(self): def test_205_glance_rabbitmq_amqp_relation(self):
'''Verify the glance:rabbitmq-server amqp relation data''' """Verify the glance:rabbitmq-server amqp relation data"""
u.log.debug('Checking glance to rmq amqp relation data...')
unit = self.glance_sentry unit = self.glance_sentry
relation = ['amqp', 'rabbitmq-server:amqp'] relation = ['amqp', 'rabbitmq-server:amqp']
expected = { expected = {
@@ -239,291 +310,180 @@ class GlanceBasicDeployment(OpenStackAmuletDeployment):
message = u.relation_error('glance amqp', ret) message = u.relation_error('glance amqp', ret)
amulet.raise_status(amulet.FAIL, msg=message) amulet.raise_status(amulet.FAIL, msg=message)
def test_image_create_delete(self): def test_300_glance_api_default_config(self):
'''Create new cirros image in glance, verify, then delete it''' """Verify default section configs in glance-api.conf and
compare some of the parameters to relation data."""
# Create a new image u.log.debug('Checking glance api config file...')
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.'''
unit = self.glance_sentry unit = self.glance_sentry
unit_ks = self.keystone_sentry
rel_gl_mq = unit.relation('amqp', 'rabbitmq-server:amqp') 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' conf = '/etc/glance/glance-api.conf'
expected = {'use_syslog': 'False', expected = {
'DEFAULT': {
'debug': 'False',
'verbose': 'False',
'use_syslog': 'False',
'log_file': '/var/log/glance/api.log',
'default_store': 'file', 'default_store': 'file',
'filesystem_store_datadir': '/var/lib/glance/images/', 'filesystem_store_datadir': '/var/lib/glance/images/',
'rabbit_userid': rel_gl_mq['username'], 'rabbit_userid': rel_gl_mq['username'],
'log_file': '/var/log/glance/api.log', 'bind_host': '0.0.0.0',
'debug': 'False', 'bind_port': '9282',
'verbose': 'False'} 'registry_host': '0.0.0.0',
section = 'DEFAULT' '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: for section, pairs in expected.iteritems():
# Defaults were different before icehouse ret = u.validate_config_data(unit, conf, section, pairs)
expected['debug'] = 'True'
expected['verbose'] = 'True'
ret = u.validate_config_data(unit, conf, section, expected)
if ret: if ret:
message = "glance-api default config error: {}".format(ret) message = "glance api config error: {}".format(ret)
amulet.raise_status(amulet.FAIL, msg=message) amulet.raise_status(amulet.FAIL, msg=message)
def test_glance_api_auth_config(self): def _get_filter_factory_expected_dict(self):
'''Verify authtoken section config in glance-api.conf using """Return expected authtoken filter factory dict for OS release"""
glance/keystone relation data.''' if self._get_openstack_release() < self.vivid_kilo:
unit_gl = self.glance_sentry # Juno and earlier
unit_ks = self.keystone_sentry val = 'keystoneclient.middleware.auth_token:filter_factory'
rel_gl_mq = unit_gl.relation('amqp', 'rabbitmq-server:amqp') else:
rel_ks_gl = unit_ks.relation('identity-service', 'glance:identity-service') # Kilo and later
conf = '/etc/glance/glance-api.conf' val = 'keystonemiddleware.auth_token: filter_factory'
section = 'keystone_authtoken'
if self._get_openstack_release() > self.precise_havana: return {'filter:authtoken': {'paste.filter_factory': val}}
# 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) def test_304_glance_api_paste_auth_config(self):
if ret: """Verify authtoken section config in glance-api-paste.ini using
message = "glance-api auth config error: {}".format(ret) glance/keystone relation data."""
amulet.raise_status(amulet.FAIL, msg=message) u.log.debug('Checking glance api paste config file...')
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')
conf = '/etc/glance/glance-api-paste.ini'
section = 'filter:authtoken'
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)
if ret:
message = "glance-api-paste auth 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')
conf = '/etc/glance/glance-registry-paste.ini'
section = 'filter:authtoken'
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)
if ret:
message = "glance-registry-paste auth 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'''
unit = self.glance_sentry unit = self.glance_sentry
conf = '/etc/glance/glance-api-paste.ini'
expected = self._get_filter_factory_expected_dict()
for section, pairs in expected.iteritems():
ret = u.validate_config_data(unit, conf, section, pairs)
if ret:
message = "glance api paste config error: {}".format(ret)
amulet.raise_status(amulet.FAIL, msg=message)
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'
expected = self._get_filter_factory_expected_dict()
for section, pairs in expected.iteritems():
ret = u.validate_config_data(unit, conf, section, pairs)
if ret:
message = "glance registry paste config error: {}".format(ret)
amulet.raise_status(amulet.FAIL, msg=message)
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
unit_ks = self.keystone_sentry
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' conf = '/etc/glance/glance-registry.conf'
expected = {'use_syslog': 'False',
expected = {
'DEFAULT': {
'use_syslog': 'False',
'log_file': '/var/log/glance/registry.log', 'log_file': '/var/log/glance/registry.log',
'debug': 'False', 'debug': 'False',
'verbose': 'False'} 'verbose': 'False',
section = 'DEFAULT' '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',
},
}
if self._get_openstack_release() <= self.precise_havana: for section, pairs in expected.iteritems():
# Defaults were different before icehouse ret = u.validate_config_data(unit, conf, section, pairs)
expected['debug'] = 'True'
expected['verbose'] = 'True'
ret = u.validate_config_data(unit, conf, section, expected)
if ret: if ret:
message = "glance-registry default config error: {}".format(ret) message = "glance registry paste config error: {}".format(ret)
amulet.raise_status(amulet.FAIL, msg=message) amulet.raise_status(amulet.FAIL, msg=message)
def test_glance_registry_auth_config(self): def test_410_glance_image_create_delete(self):
'''Verify authtoken section config in glance-registry.conf """Create new cirros image in glance, verify, then delete it."""
using glance/keystone relation data.''' u.log.debug('Creating, checking and deleting glance image...')
unit_gl = self.glance_sentry img_new = u.create_cirros_image(self.glance, "cirros-image-1")
unit_ks = self.keystone_sentry img_id = img_new.id
rel_gl_mq = unit_gl.relation('amqp', 'rabbitmq-server:amqp') u.delete_resource(self.glance.images, img_id, msg="glance image")
rel_ks_gl = unit_ks.relation('identity-service', 'glance:identity-service')
conf = '/etc/glance/glance-registry.conf'
section = 'keystone_authtoken'
if self._get_openstack_release() > self.precise_havana: def test_900_glance_restart_on_config_change(self):
# No auth config exists in this file before icehouse """Verify that the specified services are restarted when the config
expected = {'admin_user': 'glance', is changed."""
'admin_password': rel_ks_gl['service_password']} sentry = self.glance_sentry
juju_service = 'glance'
ret = u.validate_config_data(unit_gl, conf, section, expected) # Expected default and alternate values
if ret: set_default = {'use-syslog': 'False'}
message = "glance-registry keystone_authtoken config error: {}".format(ret) set_alternate = {'use-syslog': 'True'}
amulet.raise_status(amulet.FAIL, msg=message)
def test_glance_api_database_config(self): # Config file affected by juju set config change
'''Verify database config in glance-api.conf and conf_file = '/etc/glance/glance-api.conf'
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'
if self._get_openstack_release() <= self.precise_havana: # Services which are expected to restart upon config change
# Section and directive for this config changed in icehouse services = ['glance-api', 'glance-registry']
expected = {'sql_connection': db_uri, 'sql_idle_timeout': '3600'}
section = 'DEFAULT'
ret = u.validate_config_data(unit, conf, section, expected) # Make config change, check for service restarts
if ret: u.log.debug('Making config change on {}...'.format(juju_service))
message = "glance db config error: {}".format(ret) self.d.configure(juju_service, set_alternate)
amulet.raise_status(amulet.FAIL, msg=message)
def test_glance_registry_database_config(self): sleep_time = 30
'''Verify database config in glance-registry.conf and for s in services:
compare with a db uri constructed from relation data.''' u.log.debug("Checking that service restarted: {}".format(s))
unit = self.glance_sentry if not u.service_restarted(sentry, s,
conf = '/etc/glance/glance-registry.conf' conf_file, sleep_time=sleep_time):
relation = self.mysql_sentry.relation('shared-db', 'glance:shared-db') self.d.configure(juju_service, set_default)
db_uri = "mysql://{}:{}@{}/{}".format('glance', relation['password'], msg = "service {} didn't restart after config change".format(s)
relation['db_host'], 'glance') amulet.raise_status(amulet.FAIL, msg=msg)
expected = {'connection': db_uri, 'sql_idle_timeout': '3600'} sleep_time = 0
section = 'database'
if self._get_openstack_release() <= self.precise_havana: self.d.configure(juju_service, set_default)
# Section and directive for this config changed in icehouse
expected = {'sql_connection': db_uri, 'sql_idle_timeout': '3600'}
section = 'DEFAULT'
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)
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)
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)

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