update amulet test
This commit is contained in:
parent
189013a1eb
commit
6c29349c0c
18
Makefile
18
Makefile
|
@ -2,13 +2,20 @@
|
|||
PYTHON := /usr/bin/env python
|
||||
|
||||
lint:
|
||||
@flake8 --exclude hooks/charmhelpers actions hooks unit_tests tests
|
||||
@flake8 --exclude hooks/charmhelpers,tests/charmhelpers \
|
||||
actions hooks unit_tests tests
|
||||
@charm proof
|
||||
|
||||
unit_test:
|
||||
test:
|
||||
@# Bundletester expects unit tests here.
|
||||
@echo Starting tests...
|
||||
@$(PYTHON) /usr/bin/nosetests --nologcapture unit_tests
|
||||
|
||||
functional_test:
|
||||
@echo Starting Amulet tests...
|
||||
# https://bugs.launchpad.net/amulet/+bug/1320357
|
||||
@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 \
|
||||
|
@ -18,13 +25,6 @@ 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...
|
||||
# coreycb 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 test
|
||||
bzr push lp:charms/openstack-dashboard
|
||||
bzr push lp:charms/trusty/openstack-dashboard
|
||||
|
|
|
@ -4,7 +4,9 @@ maintainer: Adam Gandelman <adamg@canonical.com>
|
|||
description: |
|
||||
The OpenStack Dashboard provides a full feature web interface for interacting
|
||||
with instances, images, volumes and networks within an OpenStack deployment.
|
||||
categories: ["misc"]
|
||||
tags:
|
||||
- openstack
|
||||
- misc
|
||||
provides:
|
||||
nrpe-external-master:
|
||||
interface: nrpe-external-master
|
||||
|
|
|
@ -5,8 +5,11 @@ set -ex
|
|||
sudo add-apt-repository --yes ppa:juju/stable
|
||||
sudo apt-get update --yes
|
||||
sudo apt-get install --yes python-amulet \
|
||||
python-cinderclient \
|
||||
python-distro-info \
|
||||
python-neutronclient \
|
||||
python-glanceclient \
|
||||
python-heatclient \
|
||||
python-keystoneclient \
|
||||
python-neutronclient \
|
||||
python-novaclient \
|
||||
python-glanceclient
|
||||
python-swiftclient
|
||||
|
|
|
@ -12,8 +12,8 @@ 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
|
||||
|
@ -26,8 +26,8 @@ class OpenstackDashboardBasicDeployment(OpenStackAmuletDeployment):
|
|||
def __init__(self, series, openstack=None, source=None, git=False,
|
||||
stable=False):
|
||||
"""Deploy the entire test environment."""
|
||||
super(OpenstackDashboardBasicDeployment, self).__init__(series, openstack,
|
||||
source, stable)
|
||||
super(OpenstackDashboardBasicDeployment,
|
||||
self).__init__(series, openstack, source, stable)
|
||||
self.git = git
|
||||
self._add_services()
|
||||
self._add_relations()
|
||||
|
@ -38,22 +38,24 @@ class OpenstackDashboardBasicDeployment(OpenStackAmuletDeployment):
|
|||
def _add_services(self):
|
||||
"""Add services
|
||||
|
||||
Add the services that we're testing, where openstack-dashboard is local,
|
||||
and the rest of the service are from lp branches that are
|
||||
compatible with the local charm (e.g. stable or next).
|
||||
"""
|
||||
Add the services that we're testing, where openstack-dashboard
|
||||
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': 'openstack-dashboard'}
|
||||
other_services = [{'name': 'keystone'}, {'name': 'mysql'}]
|
||||
super(OpenstackDashboardBasicDeployment, self)._add_services(this_service,
|
||||
other_services)
|
||||
super(OpenstackDashboardBasicDeployment,
|
||||
self)._add_services(this_service, other_services)
|
||||
|
||||
def _add_relations(self):
|
||||
"""Add all of the relations for the services."""
|
||||
relations = {
|
||||
'openstack-dashboard:identity-service': 'keystone:identity-service',
|
||||
'keystone:shared-db': 'mysql:shared-db',
|
||||
'openstack-dashboard:identity-service':
|
||||
'keystone:identity-service',
|
||||
'keystone:shared-db': 'mysql:shared-db',
|
||||
}
|
||||
super(OpenstackDashboardBasicDeployment, self)._add_relations(relations)
|
||||
super(OpenstackDashboardBasicDeployment,
|
||||
self)._add_relations(relations)
|
||||
|
||||
def _configure_services(self):
|
||||
"""Configure all of the services."""
|
||||
|
@ -72,7 +74,7 @@ class OpenstackDashboardBasicDeployment(OpenStackAmuletDeployment):
|
|||
openstack_origin_git = {
|
||||
'repositories': [
|
||||
{'name': 'requirements',
|
||||
'repository': reqs_repo,
|
||||
'repository': reqs_repo,
|
||||
'branch': branch},
|
||||
{'name': 'horizon',
|
||||
'repository': horizon_repo,
|
||||
|
@ -82,7 +84,8 @@ class OpenstackDashboardBasicDeployment(OpenStackAmuletDeployment):
|
|||
'http_proxy': amulet_http_proxy,
|
||||
'https_proxy': amulet_http_proxy,
|
||||
}
|
||||
horizon_config['openstack-origin-git'] = yaml.dump(openstack_origin_git)
|
||||
horizon_config['openstack-origin-git'] = \
|
||||
yaml.dump(openstack_origin_git)
|
||||
|
||||
keystone_config = {'admin-password': 'openstack',
|
||||
'admin-token': 'ubuntutesting'}
|
||||
|
@ -90,99 +93,53 @@ class OpenstackDashboardBasicDeployment(OpenStackAmuletDeployment):
|
|||
configs = {'openstack-dashboard': horizon_config,
|
||||
'mysql': mysql_config,
|
||||
'keystone': keystone_config}
|
||||
super(OpenstackDashboardBasicDeployment, self)._configure_services(configs)
|
||||
super(OpenstackDashboardBasicDeployment,
|
||||
self)._configure_services(configs)
|
||||
|
||||
def _initialize_tests(self):
|
||||
"""Perform final initialization before tests get run."""
|
||||
# Access the sentries for inspecting service units
|
||||
self.keystone_sentry = self.d.sentry.unit['keystone/0']
|
||||
self.openstack_dashboard_sentry = self.d.sentry.unit['openstack-dashboard/0']
|
||||
self.openstack_dashboard_sentry = \
|
||||
self.d.sentry.unit['openstack-dashboard/0']
|
||||
|
||||
def test_services(self):
|
||||
"""Verify the expected services are running on the corresponding
|
||||
service units."""
|
||||
dashboard_services = ['service apache2 status']
|
||||
|
||||
commands = {
|
||||
self.keystone_sentry: ['status keystone'],
|
||||
self.openstack_dashboard_sentry: dashboard_services
|
||||
}
|
||||
|
||||
ret = u.validate_services(commands)
|
||||
if ret:
|
||||
amulet.raise_status(amulet.FAIL, msg=ret)
|
||||
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)
|
||||
|
||||
def crude_py_parse(self, file_contents, expected):
|
||||
for line in file_contents.split('\n'):
|
||||
if '=' in line:
|
||||
args = line.split('=')
|
||||
if len(args) <= 1:
|
||||
continue
|
||||
key = args[0].strip()
|
||||
value = args[1].strip()
|
||||
if key in expected.keys():
|
||||
if expected[key] != value:
|
||||
msg="Mismatch %s != %s" % (expected[key], value)
|
||||
amulet.raise_status(amulet.FAIL, msg=msg)
|
||||
args = line.split('=')
|
||||
if len(args) <= 1:
|
||||
continue
|
||||
key = args[0].strip()
|
||||
value = args[1].strip()
|
||||
if key in expected.keys():
|
||||
if expected[key] != value:
|
||||
msg = "Mismatch %s != %s" % (expected[key], value)
|
||||
amulet.raise_status(amulet.FAIL, msg=msg)
|
||||
|
||||
def test_100_services(self):
|
||||
"""Verify the expected services are running on the corresponding
|
||||
service units."""
|
||||
|
||||
def test_local_settings(self):
|
||||
unit = self.openstack_dashboard_sentry
|
||||
ksentry = self.keystone_sentry
|
||||
conf = '/etc/openstack-dashboard/local_settings.py'
|
||||
file_contents = unit.file_contents(conf)
|
||||
rdata = ksentry.relation('identity-service', 'openstack-dashboard:identity-service')
|
||||
expected = {
|
||||
'LOGIN_REDIRECT_URL': """'/horizon'""",
|
||||
'OPENSTACK_HOST': '"%s"' % (rdata['private-address']),
|
||||
'OPENSTACK_KEYSTONE_DEFAULT_ROLE': '"Member"'
|
||||
services = {
|
||||
self.keystone_sentry: ['keystone'],
|
||||
self.openstack_dashboard_sentry: ['apache2']
|
||||
}
|
||||
self.crude_py_parse(file_contents, expected)
|
||||
|
||||
def test_router_settings(self):
|
||||
if self.openstack > "icehouse":
|
||||
unit = self.openstack_dashboard_sentry
|
||||
conf = ('/usr/share/openstack-dashboard/openstack_dashboard/'
|
||||
'enabled/_40_router.py')
|
||||
file_contents = unit.file_contents(conf)
|
||||
expected = {
|
||||
'DISABLED': "True",
|
||||
}
|
||||
self.crude_py_parse(file_contents, expected)
|
||||
ret = u.validate_services_by_name(services)
|
||||
if ret:
|
||||
amulet.raise_status(amulet.FAIL, msg=ret)
|
||||
|
||||
def test_connection(self):
|
||||
unit = self.openstack_dashboard_sentry
|
||||
dashboard_relation = unit.relation('identity-service',
|
||||
'keystone:identity-service')
|
||||
dashboard_ip = dashboard_relation['private-address']
|
||||
response = urllib2.urlopen('http://%s/horizon' % (dashboard_ip))
|
||||
html = response.read()
|
||||
if 'OpenStack Dashboard' not in html:
|
||||
msg="Dashboard frontpage check failed"
|
||||
amulet.raise_status(amulet.FAIL, msg=msg)
|
||||
|
||||
def test_z_restart_on_config_change(self):
|
||||
"""Verify that the specified services are 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.
|
||||
"""
|
||||
conf = '/etc/openstack-dashboard/local_settings.py'
|
||||
services = ['apache2']
|
||||
self.d.configure('openstack-dashboard', {'use-syslog': 'True'})
|
||||
time = 120
|
||||
for s in services:
|
||||
if not u.service_restarted(self.openstack_dashboard_sentry, s, conf,
|
||||
pgrep_full=True, sleep_time=time):
|
||||
self.d.configure('openstack-dashboard', {'use-syslog': 'False'})
|
||||
msg = "service {} didn't restart after config change".format(s)
|
||||
time = 0
|
||||
self.d.configure('openstack-dashboard', {'use-syslog': 'False'})
|
||||
|
||||
def test_openstack_dashboard_identity_service_relation(self):
|
||||
"""Verify the openstack-dashboard to keystone identity-service relation data."""
|
||||
def test_200_openstack_dashboard_identity_service_relation(self):
|
||||
"""Verify the openstack-dashboard to keystone identity-service
|
||||
relation data."""
|
||||
u.log.debug('Checking dashboard:keystone id relation data...')
|
||||
unit = self.openstack_dashboard_sentry
|
||||
relation = ['identity-service', 'keystone:identity-service']
|
||||
expected = {
|
||||
|
@ -192,11 +149,14 @@ class OpenstackDashboardBasicDeployment(OpenStackAmuletDeployment):
|
|||
|
||||
ret = u.validate_relation_data(unit, relation, expected)
|
||||
if ret:
|
||||
message = u.relation_error('openstack-dashboard identity-service', ret)
|
||||
message = u.relation_error('openstack-dashboard identity-service',
|
||||
ret)
|
||||
amulet.raise_status(amulet.FAIL, msg=message)
|
||||
|
||||
def test_keystone_identity_service_relation(self):
|
||||
"""Verify the keystone to openstack-dashboard identity-service relation data."""
|
||||
def test_202_keystone_identity_service_relation(self):
|
||||
"""Verify the keystone to openstack-dashboard identity-service
|
||||
relation data."""
|
||||
u.log.debug('Checking keystone:dashboard id relation data...')
|
||||
unit = self.keystone_sentry
|
||||
relation = ['identity-service', 'openstack-dashboard:identity-service']
|
||||
expected = {
|
||||
|
@ -214,3 +174,76 @@ class OpenstackDashboardBasicDeployment(OpenStackAmuletDeployment):
|
|||
if ret:
|
||||
message = u.relation_error('keystone identity-service', ret)
|
||||
amulet.raise_status(amulet.FAIL, msg=message)
|
||||
|
||||
def test_300_local_settings(self):
|
||||
u.log.debug('Checking dashboard local settings...')
|
||||
unit = self.openstack_dashboard_sentry
|
||||
ksentry = self.keystone_sentry
|
||||
conf = '/etc/openstack-dashboard/local_settings.py'
|
||||
file_contents = unit.file_contents(conf)
|
||||
rdata = ksentry.relation('identity-service',
|
||||
'openstack-dashboard:identity-service')
|
||||
expected = {
|
||||
'LOGIN_REDIRECT_URL': """'/horizon'""",
|
||||
'OPENSTACK_HOST': '"%s"' % (rdata['private-address']),
|
||||
'OPENSTACK_KEYSTONE_DEFAULT_ROLE': '"Member"'
|
||||
}
|
||||
self.crude_py_parse(file_contents, expected)
|
||||
|
||||
def test_302_router_settings(self):
|
||||
u.log.debug('Checking dashboard router settings...')
|
||||
if self.openstack > "icehouse":
|
||||
unit = self.openstack_dashboard_sentry
|
||||
conf = ('/usr/share/openstack-dashboard/openstack_dashboard/'
|
||||
'enabled/_40_router.py')
|
||||
file_contents = unit.file_contents(conf)
|
||||
expected = {
|
||||
'DISABLED': "True",
|
||||
}
|
||||
self.crude_py_parse(file_contents, expected)
|
||||
|
||||
def test_400_connection(self):
|
||||
u.log.debug('Checking dashboard http response...')
|
||||
unit = self.openstack_dashboard_sentry
|
||||
dashboard_relation = unit.relation('identity-service',
|
||||
'keystone:identity-service')
|
||||
dashboard_ip = dashboard_relation['private-address']
|
||||
response = urllib2.urlopen('http://%s/horizon' % (dashboard_ip))
|
||||
html = response.read()
|
||||
if 'OpenStack Dashboard' not in html:
|
||||
msg = "Dashboard frontpage check failed"
|
||||
amulet.raise_status(amulet.FAIL, msg=msg)
|
||||
|
||||
def test_900_restart_on_config_change(self):
|
||||
"""Verify that the specified services are restarted when the
|
||||
config is changed."""
|
||||
|
||||
sentry = self.openstack_dashboard_sentry
|
||||
juju_service = 'openstack-dashboard'
|
||||
|
||||
# Expected default and alternate values
|
||||
set_default = {'use-syslog': 'False'}
|
||||
set_alternate = {'use-syslog': 'True'}
|
||||
|
||||
# Config file affected by juju set config change
|
||||
conf_file = '/etc/openstack-dashboard/local_settings.py'
|
||||
|
||||
# Services which are expected to restart upon config change
|
||||
services = ['apache2']
|
||||
|
||||
# Make config change, check for service restarts
|
||||
u.log.debug('Making config change on {}...'.format(juju_service))
|
||||
self.d.configure(juju_service, set_alternate)
|
||||
|
||||
sleep_time = 180
|
||||
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,
|
||||
pgrep_full=True):
|
||||
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
|
||||
|
||||
self.d.configure(juju_service, set_default)
|
||||
|
|
Loading…
Reference in New Issue