charm-keystone/tests/basic_deployment.py
2015-04-01 14:39:21 +00:00

354 lines
15 KiB
Python

#!/usr/bin/python
import amulet
import yaml
from charmhelpers.contrib.openstack.amulet.deployment import (
OpenStackAmuletDeployment
)
from charmhelpers.contrib.openstack.amulet.utils import (
OpenStackAmuletUtils,
DEBUG, # flake8: noqa
ERROR
)
# Use DEBUG to turn on debug logging
u = OpenStackAmuletUtils(ERROR)
class KeystoneBasicDeployment(OpenStackAmuletDeployment):
"""Amulet tests on a basic keystone deployment."""
def __init__(self, series=None, openstack=None, source=None, git=False, stable=False):
"""Deploy the entire test environment."""
super(KeystoneBasicDeployment, self).__init__(series, openstack, source, stable)
self.git = git
self._add_services()
self._add_relations()
self._configure_services()
self._deploy()
self._initialize_tests()
def _add_services(self):
"""Add services
Add the services that we're testing, where keystone 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': 'keystone'}
other_services = [{'name': 'mysql'}, {'name': 'cinder'}]
super(KeystoneBasicDeployment, self)._add_services(this_service,
other_services)
def _add_relations(self):
"""Add all of the relations for the services."""
relations = {'keystone:shared-db': 'mysql:shared-db',
'cinder:identity-service': 'keystone:identity-service'}
super(KeystoneBasicDeployment, self)._add_relations(relations)
def _configure_services(self):
"""Configure all of the services."""
keystone_config = {'admin-password': 'openstack',
'admin-token': 'ubuntutesting'}
if self.git:
branch = 'stable/' + self._get_openstack_release_string()
openstack_origin_git = {
'repositories': [
{'name': 'requirements',
'repository': 'git://git.openstack.org/openstack/requirements',
'branch': branch},
{'name': 'keystone',
'repository': 'git://git.openstack.org/openstack/keystone',
'branch': branch},
],
'directory': '/mnt/openstack-git',
'http_proxy': 'http://squid.internal:3128',
'https_proxy': 'https://squid.internal:3128',
}
keystone_config['openstack-origin-git'] = yaml.dump(openstack_origin_git)
mysql_config = {'dataset-size': '50%'}
cinder_config = {'block-device': 'None'}
configs = {'keystone': keystone_config,
'mysql': mysql_config,
'cinder': cinder_config}
super(KeystoneBasicDeployment, self)._configure_services(configs)
def _initialize_tests(self):
"""Perform final initialization before tests get run."""
# Access the sentries for inspecting service units
self.mysql_sentry = self.d.sentry.unit['mysql/0']
self.keystone_sentry = self.d.sentry.unit['keystone/0']
self.cinder_sentry = self.d.sentry.unit['cinder/0']
# Authenticate keystone admin
self.keystone = u.authenticate_keystone_admin(self.keystone_sentry,
user='admin',
password='openstack',
tenant='admin')
# Create a demo tenant/role/user
self.demo_tenant = 'demoTenant'
self.demo_role = 'demoRole'
self.demo_user = 'demoUser'
if not u.tenant_exists(self.keystone, self.demo_tenant):
tenant = self.keystone.tenants.create(tenant_name=self.demo_tenant,
description='demo tenant',
enabled=True)
self.keystone.roles.create(name=self.demo_role)
self.keystone.users.create(name=self.demo_user, password='password',
tenant_id=tenant.id,
email='demo@demo.com')
# Authenticate keystone demo
self.keystone_demo = u.authenticate_keystone_user(self.keystone,
user=self.demo_user,
password='password',
tenant=self.demo_tenant)
def test_services(self):
"""Verify the expected services are running on the corresponding
service units."""
commands = {
self.mysql_sentry: ['status mysql'],
self.keystone_sentry: ['status keystone'],
self.cinder_sentry: ['status cinder-api', 'status cinder-scheduler',
'status cinder-volume']
}
ret = u.validate_services(commands)
if ret:
amulet.raise_status(amulet.FAIL, msg=ret)
def test_tenants(self):
"""Verify all existing tenants."""
tenant1 = {'enabled': True,
'description': 'Created by Juju',
'name': 'services',
'id': u.not_null}
tenant2 = {'enabled': True,
'description': 'demo tenant',
'name': 'demoTenant',
'id': u.not_null}
tenant3 = {'enabled': True,
'description': 'Created by Juju',
'name': 'admin',
'id': u.not_null}
expected = [tenant1, tenant2, tenant3]
actual = self.keystone.tenants.list()
ret = u.validate_tenant_data(expected, actual)
if ret:
amulet.raise_status(amulet.FAIL, msg=ret)
def test_roles(self):
"""Verify all existing roles."""
role1 = {'name': 'demoRole', 'id': u.not_null}
role2 = {'name': 'Admin', 'id': u.not_null}
expected = [role1, role2]
actual = self.keystone.roles.list()
ret = u.validate_role_data(expected, actual)
if ret:
amulet.raise_status(amulet.FAIL, msg=ret)
def test_users(self):
"""Verify all existing roles."""
user1 = {'name': 'demoUser',
'enabled': True,
'tenantId': u.not_null,
'id': u.not_null,
'email': 'demo@demo.com'}
user2 = {'name': 'admin',
'enabled': True,
'tenantId': u.not_null,
'id': u.not_null,
'email': 'juju@localhost'}
user3 = {'name': 'cinder',
'enabled': True,
'tenantId': u.not_null,
'id': u.not_null,
'email': u'juju@localhost'}
expected = [user1, user2, user3]
actual = self.keystone.users.list()
ret = u.validate_user_data(expected, actual)
if ret:
amulet.raise_status(amulet.FAIL, msg=ret)
def test_service_catalog(self):
"""Verify that the service catalog endpoint data is valid."""
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.precise_essex:
endpoint_vol['id'] = u.not_null
endpoint_id['id'] = u.not_null
expected = {'volume': [endpoint_vol], 'identity': [endpoint_id]}
actual = self.keystone_demo.service_catalog.get_endpoints()
ret = u.validate_svc_catalog_endpoint_data(expected, actual)
if ret:
amulet.raise_status(amulet.FAIL, msg=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 test_cinder_endpoint(self):
"""Verify the cinder endpoint data."""
endpoints = self.keystone.endpoints.list()
admin_port = internal_port = public_port = '8776'
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='cinder endpoint: {}'.format(ret))
def test_keystone_shared_db_relation(self):
"""Verify the keystone shared-db relation data"""
unit = self.keystone_sentry
relation = ['shared-db', 'mysql:shared-db']
expected = {
'username': 'keystone',
'private-address': u.valid_ip,
'hostname': u.valid_ip,
'database': 'keystone'
}
ret = u.validate_relation_data(unit, relation, expected)
if ret:
message = u.relation_error('keystone shared-db', ret)
amulet.raise_status(amulet.FAIL, msg=message)
def test_mysql_shared_db_relation(self):
"""Verify the mysql shared-db relation data"""
unit = self.mysql_sentry
relation = ['shared-db', 'keystone:shared-db']
expected_data = {
'private-address': u.valid_ip,
'password': u.not_null,
'db_host': u.valid_ip
}
ret = u.validate_relation_data(unit, relation, expected_data)
if ret:
message = u.relation_error('mysql shared-db', ret)
amulet.raise_status(amulet.FAIL, msg=message)
def test_keystone_identity_service_relation(self):
"""Verify the keystone identity-service relation data"""
unit = self.keystone_sentry
relation = ['identity-service', 'cinder:identity-service']
expected = {
'service_protocol': 'http',
'service_tenant': 'services',
'admin_token': 'ubuntutesting',
'service_password': u.not_null,
'service_port': '5000',
'auth_port': '35357',
'auth_protocol': 'http',
'private-address': u.valid_ip,
'auth_host': u.valid_ip,
'service_username': 'cinder',
'service_tenant_id': u.not_null,
'service_host': u.valid_ip
}
ret = u.validate_relation_data(unit, relation, expected)
if ret:
message = u.relation_error('cinder identity-service', ret)
amulet.raise_status(amulet.FAIL, msg=message)
def test_cinder_identity_service_relation(self):
"""Verify the cinder identity-service relation data"""
unit = self.cinder_sentry
relation = ['identity-service', 'keystone:identity-service']
expected = {
'service': 'cinder',
'region': 'RegionOne',
'public_url': u.valid_url,
'internal_url': u.valid_url,
'private-address': u.valid_ip,
'admin_url': u.valid_url
}
ret = u.validate_relation_data(unit, relation, expected)
if ret:
message = u.relation_error('cinder identity-service', ret)
amulet.raise_status(amulet.FAIL, msg=message)
def test_z_restart_on_config_change(self):
"""Verify that keystone 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.
"""
self.d.configure('keystone', {'verbose': 'True'})
if not u.service_restarted(self.keystone_sentry, 'keystone-all',
'/etc/keystone/keystone.conf',
sleep_time=30):
self.d.configure('keystone', {'verbose': 'False'})
message = "keystone service didn't restart after config change"
amulet.raise_status(amulet.FAIL, msg=message)
self.d.configure('keystone', {'verbose': 'False'})
def test_default_config(self):
"""Verify the data in the keystone config file's default section,
comparing some of the variables vs relation data."""
unit = self.keystone_sentry
conf = '/etc/keystone/keystone.conf'
relation = unit.relation('identity-service', 'cinder:identity-service')
expected = {'admin_token': relation['admin_token'],
'admin_port': '35347',
'public_port': '4990',
'use_syslog': 'False',
'log_config': '/etc/keystone/logging.conf',
'debug': 'False',
'verbose': 'False'}
ret = u.validate_config_data(unit, conf, 'DEFAULT', expected)
if ret:
message = "keystone config error: {}".format(ret)
amulet.raise_status(amulet.FAIL, msg=message)
def test_database_config(self):
"""Verify the data in the keystone config file's database (or sql
depending on release) section, comparing vs relation data."""
unit = self.keystone_sentry
conf = '/etc/keystone/keystone.conf'
relation = self.mysql_sentry.relation('shared-db', 'keystone:shared-db')
db_uri = "mysql://{}:{}@{}/{}".format('keystone', relation['password'],
relation['db_host'], 'keystone')
expected = {'connection': db_uri, 'idle_timeout': '200'}
if self._get_openstack_release() > self.precise_havana:
ret = u.validate_config_data(unit, conf, 'database', expected)
else:
ret = u.validate_config_data(unit, conf, 'sql', expected)
if ret:
message = "keystone config error: {}".format(ret)
amulet.raise_status(amulet.FAIL, msg=message)