From d22a627adb9790c72be6b7aae7cc896cfcc5145c Mon Sep 17 00:00:00 2001 From: Ryan Beisner Date: Tue, 30 Jun 2015 20:43:41 +0000 Subject: [PATCH] update tests --- Makefile | 25 +- metadata.yaml | 2 +- tests/00-setup | 6 +- tests/017-basic-trusty-kilo | 0 tests/019-basic-vivid-kilo | 0 tests/020-basic-trusty-liberty | 11 + tests/021-basic-wily-liberty | 9 + tests/README | 9 + tests/basic_deployment.py | 586 +++++++++++++++------------------ tests/tests.yaml | 18 + 10 files changed, 336 insertions(+), 330 deletions(-) mode change 100644 => 100755 tests/017-basic-trusty-kilo mode change 100644 => 100755 tests/019-basic-vivid-kilo create mode 100644 tests/020-basic-trusty-liberty create mode 100644 tests/021-basic-wily-liberty create mode 100644 tests/tests.yaml diff --git a/Makefile b/Makefile index bb075a0f..607af27a 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/metadata.yaml b/metadata.yaml index 5c1f6ea5..47cc9b41 100644 --- a/metadata.yaml +++ b/metadata.yaml @@ -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: diff --git a/tests/00-setup b/tests/00-setup index 1243ec43..ee5f0332 100755 --- a/tests/00-setup +++ b/tests/00-setup @@ -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 diff --git a/tests/017-basic-trusty-kilo b/tests/017-basic-trusty-kilo old mode 100644 new mode 100755 diff --git a/tests/019-basic-vivid-kilo b/tests/019-basic-vivid-kilo old mode 100644 new mode 100755 diff --git a/tests/020-basic-trusty-liberty b/tests/020-basic-trusty-liberty new file mode 100644 index 00000000..85f0bf77 --- /dev/null +++ b/tests/020-basic-trusty-liberty @@ -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() diff --git a/tests/021-basic-wily-liberty b/tests/021-basic-wily-liberty new file mode 100644 index 00000000..24ddcad5 --- /dev/null +++ b/tests/021-basic-wily-liberty @@ -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() diff --git a/tests/README b/tests/README index db2e015d..c82d50e7 100644 --- a/tests/README +++ b/tests/README @@ -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 diff --git a/tests/basic_deployment.py b/tests/basic_deployment.py index d0a8db8e..4192985e 100644 --- a/tests/basic_deployment.py +++ b/tests/basic_deployment.py @@ -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) diff --git a/tests/tests.yaml b/tests/tests.yaml new file mode 100644 index 00000000..db533a1e --- /dev/null +++ b/tests/tests.yaml @@ -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