update makefile, amulet test dependencies, test definitions, amulet test

This commit is contained in:
Ryan Beisner 2015-08-22 03:57:12 +00:00
parent 89157b540e
commit 67ed09adbe
8 changed files with 262 additions and 178 deletions

View File

@ -2,12 +2,18 @@
PYTHON := /usr/bin/env python PYTHON := /usr/bin/env python
lint: lint:
@flake8 --exclude hooks/charmhelpers actions hooks unit_tests tests @flake8 --exclude hooks/charmhelpers,tests/charmhelpers \
actions hooks unit_tests tests
@charm proof @charm proof
unit_test: test:
@echo Starting tests... @# Bundletester expects unit tests here.
@$(PYTHON) /usr/bin/nosetests --nologcapture unit_tests @echo Starting 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
@ -18,13 +24,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-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...
# 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 unit_test
bzr push lp:charms/neutron-api bzr push lp:charms/neutron-api
bzr push lp:charms/trusty/neutron-api bzr push lp:charms/trusty/neutron-api

View File

@ -4,8 +4,13 @@ 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 amulet \
python-neutronclient \ python-cinderclient \
python-distro-info \
python-glanceclient \
python-heatclient \
python-keystoneclient \ python-keystoneclient \
python-neutronclient \
python-novaclient \ python-novaclient \
python-glanceclient python-pika \
python-swiftclient

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 neutron-api deployment on trusty-liberty."""
from basic_deployment import NeutronAPIBasicDeployment
if __name__ == '__main__':
deployment = NeutronAPIBasicDeployment(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 neutron-api deployment on wily-liberty."""
from basic_deployment import NeutronAPIBasicDeployment
if __name__ == '__main__':
deployment = NeutronAPIBasicDeployment(series='wily')
deployment.run_tests()

View File

@ -1,6 +1,39 @@
This directory provides Amulet tests that focus on verification of This directory provides Amulet tests that focus on verification of
neutron-api deployments. neutron-api deployments.
test_* methods are called in lexical sort order, although each individual test
should be idempotent, and expected to pass regardless of run 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
Common relation definitions:
- [ neutron-api, mysql ]
- [ neutron-api, rabbitmq-server ]
- [ neutron-api, nova-cloud-controller ]
- [ neutron-api, neutron-openvswitch ]
- [ neutron-api, keystone ]
- [ neutron-api, neutron-gateway ]
Resultant relations of neutron-api service:
relations:
amqp:
- rabbitmq-server
cluster:
- neutron-api
identity-service:
- keystone
neutron-api:
- nova-cloud-controller
neutron-plugin-api:
- neutron-openvswitch
shared-db:
- mysql
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

@ -1,38 +1,6 @@
#!/usr/bin/python #!/usr/bin/python
""" """
Basic neutron-api functional test. Basic neutron-api functional test.
test_* methods are called in sort order.
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
Common relation definitions:
- [ neutron-api, mysql ]
- [ neutron-api, rabbitmq-server ]
- [ neutron-api, nova-cloud-controller ]
- [ neutron-api, neutron-openvswitch ]
- [ neutron-api, keystone ]
- [ neutron-api, neutron-gateway ]
Resultant relations of neutron-api service:
relations:
amqp:
- rabbitmq-server
cluster:
- neutron-api
identity-service:
- keystone
neutron-api:
- nova-cloud-controller
neutron-plugin-api: # not inspected due to
- neutron-openvswitch # bug 1421388
shared-db:
- mysql
""" """
import amulet import amulet
@ -46,8 +14,8 @@ 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
@ -78,10 +46,11 @@ class NeutronAPIBasicDeployment(OpenStackAmuletDeployment):
""" """
this_service = {'name': 'neutron-api'} this_service = {'name': 'neutron-api'}
other_services = [{'name': 'mysql'}, other_services = [{'name': 'mysql'},
{'name': 'rabbitmq-server'}, {'name': 'keystone'}, {'name': 'rabbitmq-server'},
{'name': 'keystone'},
{'name': 'neutron-openvswitch'}, {'name': 'neutron-openvswitch'},
{'name': 'nova-cloud-controller'}, {'name': 'nova-cloud-controller'},
{'name': 'quantum-gateway'}, {'name': 'neutron-gateway'},
{'name': 'nova-compute'}] {'name': 'nova-compute'}]
super(NeutronAPIBasicDeployment, self)._add_services(this_service, super(NeutronAPIBasicDeployment, self)._add_services(this_service,
other_services) other_services)
@ -92,16 +61,23 @@ class NeutronAPIBasicDeployment(OpenStackAmuletDeployment):
'neutron-api:shared-db': 'mysql:shared-db', 'neutron-api:shared-db': 'mysql:shared-db',
'neutron-api:amqp': 'rabbitmq-server:amqp', 'neutron-api:amqp': 'rabbitmq-server:amqp',
'neutron-api:neutron-api': 'nova-cloud-controller:neutron-api', 'neutron-api:neutron-api': 'nova-cloud-controller:neutron-api',
'neutron-api:neutron-plugin-api': 'quantum-gateway:' 'neutron-api:neutron-plugin-api': 'neutron-gateway:'
'neutron-plugin-api',
'neutron-api:neutron-plugin-api': 'neutron-openvswitch:'
'neutron-plugin-api', 'neutron-plugin-api',
'neutron-api:identity-service': 'keystone:identity-service', 'neutron-api:identity-service': 'keystone:identity-service',
'keystone:shared-db': 'mysql:shared-db', 'keystone:shared-db': 'mysql:shared-db',
'nova-compute:neutron-plugin': 'neutron-openvswitch:neutron-plugin', 'nova-compute:neutron-plugin': 'neutron-openvswitch:'
'neutron-plugin',
'nova-cloud-controller:shared-db': 'mysql:shared-db', 'nova-cloud-controller:shared-db': 'mysql:shared-db',
} }
# NOTE(beisner): relate this separately due to the resulting
# duplicate dictionary key if included in the relations dict.
relations_more = {
'neutron-api:neutron-plugin-api': 'neutron-openvswitch:'
'neutron-plugin-api',
}
super(NeutronAPIBasicDeployment, self)._add_relations(relations) super(NeutronAPIBasicDeployment, self)._add_relations(relations)
super(NeutronAPIBasicDeployment, self)._add_relations(relations_more)
def _configure_services(self): def _configure_services(self):
"""Configure all of the services.""" """Configure all of the services."""
@ -122,14 +98,17 @@ class NeutronAPIBasicDeployment(OpenStackAmuletDeployment):
'http_proxy': amulet_http_proxy, 'http_proxy': amulet_http_proxy,
'https_proxy': amulet_http_proxy, 'https_proxy': amulet_http_proxy,
} }
neutron_api_config['openstack-origin-git'] = yaml.dump(openstack_origin_git) neutron_api_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'}
nova_cc_config = {'network-manager': 'Quantum', nova_cc_config = {'network-manager': 'Quantum',
'quantum-security-groups': 'yes'} 'quantum-security-groups': 'yes'}
configs = {'neutron-api': neutron_api_config, configs = {
'keystone': keystone_config, 'neutron-api': neutron_api_config,
'nova-cloud-controller': nova_cc_config} 'keystone': keystone_config,
'nova-cloud-controller': nova_cc_config
}
super(NeutronAPIBasicDeployment, self)._configure_services(configs) super(NeutronAPIBasicDeployment, self)._configure_services(configs)
def _initialize_tests(self): def _initialize_tests(self):
@ -139,8 +118,9 @@ class NeutronAPIBasicDeployment(OpenStackAmuletDeployment):
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']
self.nova_cc_sentry = self.d.sentry.unit['nova-cloud-controller/0'] self.nova_cc_sentry = self.d.sentry.unit['nova-cloud-controller/0']
self.quantum_gateway_sentry = self.d.sentry.unit['quantum-gateway/0'] self.neutron_sentry = self.d.sentry.unit['neutron-gateway/0']
self.neutron_api_sentry = self.d.sentry.unit['neutron-api/0'] self.neutron_api_sentry = self.d.sentry.unit['neutron-api/0']
self.neutron_ovs_sentry = self.d.sentry.unit['neutron-openvswitch/0']
self.nova_compute_sentry = self.d.sentry.unit['nova-compute/0'] self.nova_compute_sentry = self.d.sentry.unit['nova-compute/0']
u.log.debug('openstack release val: {}'.format( u.log.debug('openstack release val: {}'.format(
self._get_openstack_release())) self._get_openstack_release()))
@ -149,48 +129,46 @@ class NeutronAPIBasicDeployment(OpenStackAmuletDeployment):
# Let things settle a bit before moving forward # Let things settle a bit before moving forward
time.sleep(30) time.sleep(30)
def test_100_services(self): def test_100_services(self):
"""Verify the expected services are running on the corresponding """Verify the expected services are running on the corresponding
service units.""" service units."""
u.log.debug('Checking status of system services...') u.log.debug('Checking status of system services...')
# Fails vivid-kilo, bug 1454754 neutron_api_services = ['neutron-server']
neutron_api_services = ['status neutron-server'] neutron_services = ['neutron-dhcp-agent',
neutron_services = ['status neutron-dhcp-agent', 'neutron-lbaas-agent',
'status neutron-lbaas-agent', 'neutron-metadata-agent',
'status neutron-metadata-agent', 'neutron-plugin-openvswitch-agent',
'status neutron-plugin-openvswitch-agent', 'neutron-ovs-cleanup']
'status neutron-ovs-cleanup']
if self._get_openstack_release() <= self.trusty_juno: if self._get_openstack_release() <= self.trusty_juno:
neutron_services.append('status neutron-vpn-agent') neutron_services.append('neutron-vpn-agent')
if self._get_openstack_release() < self.trusty_kilo: if self._get_openstack_release() < self.trusty_kilo:
# Juno or earlier # Juno or earlier
neutron_services.append('status neutron-metering-agent') neutron_services.append('neutron-metering-agent')
nova_cc_services = ['status nova-api-ec2', nova_cc_services = ['nova-api-ec2',
'status nova-api-os-compute', 'nova-api-os-compute',
'status nova-objectstore', 'nova-objectstore',
'status nova-cert', 'nova-cert',
'status nova-scheduler', 'nova-scheduler',
'status nova-conductor'] 'nova-conductor']
commands = { services = {
self.mysql_sentry: ['status mysql'], self.mysql_sentry: ['mysql'],
self.keystone_sentry: ['status keystone'], self.keystone_sentry: ['keystone'],
self.nova_cc_sentry: nova_cc_services, self.nova_cc_sentry: nova_cc_services,
self.quantum_gateway_sentry: neutron_services, self.neutron_sentry: neutron_services,
self.neutron_api_sentry: neutron_api_services, self.neutron_api_sentry: neutron_api_services,
} }
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_200_neutron_api_shared_db_relation(self): def test_200_neutron_api_shared_db_relation(self):
"""Verify the neutron-api to mysql shared-db relation data""" """Verify the neutron-api to mysql shared-db relation data"""
u.log.debug('Checking neutron-api:mysql relation data...') u.log.debug('Checking neutron-api:mysql db relation data...')
unit = self.neutron_api_sentry unit = self.neutron_api_sentry
relation = ['shared-db', 'mysql:shared-db'] relation = ['shared-db', 'mysql:shared-db']
expected = { expected = {
@ -207,12 +185,13 @@ class NeutronAPIBasicDeployment(OpenStackAmuletDeployment):
def test_201_shared_db_neutron_api_relation(self): def test_201_shared_db_neutron_api_relation(self):
"""Verify the mysql to neutron-api shared-db relation data""" """Verify the mysql to neutron-api shared-db relation data"""
u.log.debug('Checking mysql:neutron-api relation data...') u.log.debug('Checking mysql:neutron-api db relation data...')
unit = self.mysql_sentry unit = self.mysql_sentry
relation = ['shared-db', 'neutron-api:shared-db'] relation = ['shared-db', 'neutron-api:shared-db']
expected = { expected = {
'db_host': u.valid_ip, 'db_host': u.valid_ip,
'private-address': u.valid_ip, 'private-address': u.valid_ip,
'password': u.not_null
} }
if self._get_openstack_release() == self.precise_icehouse: if self._get_openstack_release() == self.precise_icehouse:
@ -223,8 +202,7 @@ class NeutronAPIBasicDeployment(OpenStackAmuletDeployment):
expected['allowed_units'] = 'neutron-api/0' expected['allowed_units'] = 'neutron-api/0'
ret = u.validate_relation_data(unit, relation, expected) ret = u.validate_relation_data(unit, relation, expected)
rel_data = unit.relation('shared-db', 'neutron-api:shared-db') if ret:
if ret or 'password' not in rel_data:
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)
@ -249,25 +227,25 @@ class NeutronAPIBasicDeployment(OpenStackAmuletDeployment):
u.log.debug('Checking amqp:neutron-api relation data...') u.log.debug('Checking amqp:neutron-api relation data...')
unit = self.rabbitmq_sentry unit = self.rabbitmq_sentry
relation = ['amqp', 'neutron-api:amqp'] relation = ['amqp', 'neutron-api:amqp']
rel_data = unit.relation('amqp', 'neutron-api:amqp')
expected = { expected = {
'hostname': u.valid_ip, 'hostname': u.valid_ip,
'private-address': u.valid_ip, 'private-address': u.valid_ip,
'password': u.not_null
} }
ret = u.validate_relation_data(unit, relation, expected) ret = u.validate_relation_data(unit, relation, expected)
if ret or not 'password' in rel_data: if ret:
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_204_neutron_api_identity_relation(self): def test_204_neutron_api_keystone_identity_relation(self):
"""Verify the neutron-api to keystone identity-service relation data""" """Verify the neutron-api to keystone identity-service relation data"""
u.log.debug('Checking neutron-api:keystone relation data...') u.log.debug('Checking neutron-api:keystone id relation data...')
unit = self.neutron_api_sentry unit = self.neutron_api_sentry
relation = ['identity-service', 'keystone:identity-service'] relation = ['identity-service', 'keystone:identity-service']
api_ip = unit.relation('identity-service', api_ip = unit.relation('identity-service',
'keystone:identity-service')['private-address'] 'keystone:identity-service')['private-address']
api_endpoint = "http://%s:9696" % (api_ip) api_endpoint = 'http://{}:9696'.format(api_ip)
expected = { expected = {
'private-address': u.valid_ip, 'private-address': u.valid_ip,
'quantum_region': 'RegionOne', 'quantum_region': 'RegionOne',
@ -284,12 +262,12 @@ class NeutronAPIBasicDeployment(OpenStackAmuletDeployment):
def test_205_keystone_neutron_api_identity_relation(self): def test_205_keystone_neutron_api_identity_relation(self):
"""Verify the keystone to neutron-api identity-service relation data""" """Verify the keystone to neutron-api identity-service relation data"""
u.log.debug('Checking keystone:neutron-api relation data...') u.log.debug('Checking keystone:neutron-api id relation data...')
unit = self.keystone_sentry unit = self.keystone_sentry
relation = ['identity-service', 'neutron-api:identity-service'] relation = ['identity-service', 'neutron-api:identity-service']
id_relation = unit.relation('identity-service', rel_ks_id = unit.relation('identity-service',
'neutron-api:identity-service') 'neutron-api:identity-service')
id_ip = id_relation['private-address'] id_ip = rel_ks_id['private-address']
expected = { expected = {
'admin_token': 'ubuntutesting', 'admin_token': 'ubuntutesting',
'auth_host': id_ip, 'auth_host': id_ip,
@ -303,12 +281,46 @@ class NeutronAPIBasicDeployment(OpenStackAmuletDeployment):
message = u.relation_error('neutron-api identity-service', ret) message = u.relation_error('neutron-api identity-service', ret)
amulet.raise_status(amulet.FAIL, msg=message) amulet.raise_status(amulet.FAIL, msg=message)
def test_206_neutron_api_plugin_relation(self): def test_206_neutron_api_neutron_ovs_plugin_api_relation(self):
"""Verify neutron-api to neutron-openvswitch neutron-plugin-api""" """Verify neutron-api to neutron-openvswitch neutron-plugin-api"""
u.log.debug('Checking neutron-api:neutron-ovs relation data...') u.log.debug('Checking neutron-api:neutron-ovs plugin-api '
'relation data...')
unit = self.neutron_api_sentry unit = self.neutron_api_sentry
relation = ['neutron-plugin-api', relation = ['neutron-plugin-api',
'neutron-openvswitch:neutron-plugin-api'] 'neutron-openvswitch:neutron-plugin-api']
#
u.log.debug(unit.relation(relation[0], relation[1]))
expected = {
'auth_host': u.valid_ip,
'auth_port': '35357',
'auth_protocol': 'http',
'enable-dvr': 'False',
'enable-l3ha': 'False',
'l2-population': 'True',
'neutron-security-groups': 'False',
'overlay-network-type': 'gre',
'private-address': u.valid_ip,
'region': 'RegionOne',
'service_host': u.valid_ip,
'service_password': u.not_null,
'service_port': '5000',
'service_protocol': 'http',
'service_tenant': 'services',
'service_username': 'quantum',
}
ret = u.validate_relation_data(unit, relation, expected)
if ret:
message = u.relation_error(
'neutron-api neutron-ovs neutronplugin-api', ret)
amulet.raise_status(amulet.FAIL, msg=message)
def test_207_neutron_ovs_neutron_api_plugin_api_relation(self):
"""Verify neutron-openvswitch to neutron-api neutron-plugin-api"""
u.log.debug('Checking neutron-ovs:neutron-api plugin-api '
'relation data...')
unit = self.neutron_ovs_sentry
relation = ['neutron-plugin-api',
'neutron-api:neutron-plugin-api']
expected = { expected = {
'private-address': u.valid_ip, 'private-address': u.valid_ip,
} }
@ -317,14 +329,14 @@ class NeutronAPIBasicDeployment(OpenStackAmuletDeployment):
message = u.relation_error('neutron-api neutron-plugin-api', ret) message = u.relation_error('neutron-api neutron-plugin-api', ret)
amulet.raise_status(amulet.FAIL, msg=message) amulet.raise_status(amulet.FAIL, msg=message)
def test_207_neutron_api_novacc_relation(self): def test_208_neutron_api_novacc_relation(self):
"""Verify the neutron-api to nova-cloud-controller relation data""" """Verify the neutron-api to nova-cloud-controller relation data"""
u.log.debug('Checking neutron-api:novacc relation data...') u.log.debug('Checking neutron-api:novacc relation data...')
unit = self.neutron_api_sentry unit = self.neutron_api_sentry
relation = ['neutron-api', 'nova-cloud-controller:neutron-api'] relation = ['neutron-api', 'nova-cloud-controller:neutron-api']
api_ip = unit.relation('identity-service', api_ip = unit.relation('identity-service',
'keystone:identity-service')['private-address'] 'keystone:identity-service')['private-address']
api_endpoint = "http://%s:9696" % (api_ip) api_endpoint = 'http://{}:9696'.format(api_ip)
expected = { expected = {
'private-address': api_ip, 'private-address': api_ip,
'neutron-plugin': 'ovs', 'neutron-plugin': 'ovs',
@ -336,14 +348,14 @@ class NeutronAPIBasicDeployment(OpenStackAmuletDeployment):
message = u.relation_error('neutron-api neutron-api', ret) message = u.relation_error('neutron-api neutron-api', ret)
amulet.raise_status(amulet.FAIL, msg=message) amulet.raise_status(amulet.FAIL, msg=message)
def test_208_novacc_neutron_api_relation(self): def test_209_novacc_neutron_api_relation(self):
"""Verify the nova-cloud-controller to neutron-api relation data""" """Verify the nova-cloud-controller to neutron-api relation data"""
u.log.debug('Checking novacc:neutron-api relation data...') u.log.debug('Checking novacc:neutron-api relation data...')
unit = self.nova_cc_sentry unit = self.nova_cc_sentry
relation = ['neutron-api', 'neutron-api:neutron-api'] relation = ['neutron-api', 'neutron-api:neutron-api']
cc_ip = unit.relation('neutron-api', cc_ip = unit.relation('neutron-api',
'neutron-api:neutron-api')['private-address'] 'neutron-api:neutron-api')['private-address']
cc_endpoint = "http://%s:8774/v2" % (cc_ip) cc_endpoint = 'http://{}:8774/v2'.format(cc_ip)
expected = { expected = {
'private-address': cc_ip, 'private-address': cc_ip,
'nova_url': cc_endpoint, 'nova_url': cc_endpoint,
@ -353,34 +365,6 @@ class NeutronAPIBasicDeployment(OpenStackAmuletDeployment):
message = u.relation_error('nova-cc neutron-api', ret) message = u.relation_error('nova-cc neutron-api', ret)
amulet.raise_status(amulet.FAIL, msg=message) amulet.raise_status(amulet.FAIL, msg=message)
# XXX Test missing to examine the relation data neutron-openvswitch is
# receiving. Current;y this data cannot be interegated due to
# Bug#1421388
def test_900_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.
"""
u.log.debug('Checking novacc neutron-api relation data...')
conf = '/etc/neutron/neutron.conf'
services = ['neutron-server']
u.log.debug('Making config change on neutron-api service...')
self.d.configure('neutron-api', {'use-syslog': 'True'})
stime = 60
for s in services:
u.log.debug("Checking that service restarted: {}".format(s))
if not u.service_restarted(self.neutron_api_sentry, s, conf,
pgrep_full=True, sleep_time=stime):
self.d.configure('neutron-api', {'use-syslog': 'False'})
msg = "service {} didn't restart after config change".format(s)
amulet.raise_status(amulet.FAIL, msg=msg)
stime = 0
self.d.configure('neutron-api', {'use-syslog': 'False'})
def test_300_neutron_config(self): def test_300_neutron_config(self):
"""Verify the data in the neutron config file.""" """Verify the data in the neutron config file."""
u.log.debug('Checking neutron.conf config file data...') u.log.debug('Checking neutron.conf config file data...')
@ -389,34 +373,36 @@ class NeutronAPIBasicDeployment(OpenStackAmuletDeployment):
'neutron-api:neutron-api') 'neutron-api:neutron-api')
rabbitmq_relation = self.rabbitmq_sentry.relation('amqp', rabbitmq_relation = self.rabbitmq_sentry.relation('amqp',
'neutron-api:amqp') 'neutron-api:amqp')
ks_rel = self.keystone_sentry.relation('identity-service', rel_napi_ks = self.keystone_sentry.relation(
'neutron-api:identity-service') 'identity-service', 'neutron-api:identity-service')
nova_auth_url = '%s://%s:%s/v2.0' % (ks_rel['auth_protocol'], nova_auth_url = '{}://{}:{}/v2.0'.format(rel_napi_ks['auth_protocol'],
ks_rel['auth_host'], rel_napi_ks['auth_host'],
ks_rel['auth_port']) rel_napi_ks['auth_port'])
db_relation = self.mysql_sentry.relation('shared-db', rel_napi_my = self.mysql_sentry.relation('shared-db',
'neutron-api:shared-db') 'neutron-api:shared-db')
db_conn = 'mysql://neutron:%s@%s/neutron' % (db_relation['password'], db_conn = 'mysql://neutron:{}@{}/neutron'.format(
db_relation['db_host']) rel_napi_my['password'], rel_napi_my['db_host'])
conf = '/etc/neutron/neutron.conf' conf = '/etc/neutron/neutron.conf'
expected = { expected = {
'DEFAULT': { 'DEFAULT': {
'verbose': 'False', 'verbose': 'False',
# True on Kilo!?:
'debug': 'False', 'debug': 'False',
'bind_port': '9686', 'bind_port': '9686',
'nova_url': cc_relation['nova_url'], 'nova_url': cc_relation['nova_url'],
'nova_region_name': 'RegionOne', 'nova_region_name': 'RegionOne',
'nova_admin_username': ks_rel['service_username'], 'nova_admin_username': rel_napi_ks['service_username'],
'nova_admin_tenant_id': ks_rel['service_tenant_id'], 'nova_admin_tenant_id': rel_napi_ks['service_tenant_id'],
'nova_admin_password': ks_rel['service_password'], 'nova_admin_password': rel_napi_ks['service_password'],
'nova_admin_auth_url': nova_auth_url, 'nova_admin_auth_url': nova_auth_url,
}, },
'keystone_authtoken': { 'keystone_authtoken': {
'signing_dir': '/var/cache/neutron', 'signing_dir': '/var/cache/neutron',
'admin_tenant_name': 'services', 'admin_tenant_name': 'services',
'admin_user': 'quantum', 'admin_user': 'quantum',
'admin_password': ks_rel['service_password'], 'admin_password': rel_napi_ks['service_password'],
}, },
'database': { 'database': {
'connection': db_conn, 'connection': db_conn,
@ -425,36 +411,28 @@ class NeutronAPIBasicDeployment(OpenStackAmuletDeployment):
if self._get_openstack_release() >= self.trusty_kilo: if self._get_openstack_release() >= self.trusty_kilo:
# Kilo or later # Kilo or later
expected.update( expected['oslo_messaging_rabbit'] = {
{ 'rabbit_userid': 'neutron',
'oslo_messaging_rabbit': { 'rabbit_virtual_host': 'openstack',
'rabbit_userid': 'neutron', 'rabbit_password': rabbitmq_relation['password'],
'rabbit_virtual_host': 'openstack', 'rabbit_host': rabbitmq_relation['hostname']
'rabbit_password': rabbitmq_relation['password'], }
'rabbit_host': rabbitmq_relation['hostname']
}
}
)
else: else:
# Juno or earlier # Juno or earlier
expected['DEFAULT'].update( expected['DEFAULT'].update({
{ 'rabbit_userid': 'neutron',
'rabbit_userid': 'neutron', 'rabbit_virtual_host': 'openstack',
'rabbit_virtual_host': 'openstack', 'rabbit_password': rabbitmq_relation['password'],
'rabbit_password': rabbitmq_relation['password'], 'rabbit_host': rabbitmq_relation['hostname']
'rabbit_host': rabbitmq_relation['hostname'] })
} expected['keystone_authtoken'].update({
) 'service_protocol': rel_napi_ks['service_protocol'],
expected['keystone_authtoken'].update( 'service_host': rel_napi_ks['service_host'],
{ 'service_port': rel_napi_ks['service_port'],
'service_protocol': ks_rel['service_protocol'], 'auth_host': rel_napi_ks['auth_host'],
'service_host': ks_rel['service_host'], 'auth_port': rel_napi_ks['auth_port'],
'service_port': ks_rel['service_port'], 'auth_protocol': rel_napi_ks['auth_protocol']
'auth_host': ks_rel['auth_host'], })
'auth_port': ks_rel['auth_port'],
'auth_protocol': ks_rel['auth_protocol']
}
)
for section, pairs in expected.iteritems(): for section, pairs in expected.iteritems():
ret = u.validate_config_data(unit, conf, section, pairs) ret = u.validate_config_data(unit, conf, section, pairs)
@ -495,21 +473,50 @@ class NeutronAPIBasicDeployment(OpenStackAmuletDeployment):
if self._get_openstack_release() >= self.trusty_kilo: if self._get_openstack_release() >= self.trusty_kilo:
# Kilo or later # Kilo or later
expected['ml2'].update( expected['ml2'].update({
{ 'mechanism_drivers': 'openvswitch,l2population'
'mechanism_drivers': 'openvswitch,l2population' })
}
)
else: else:
# Juno or earlier # Juno or earlier
expected['ml2'].update( expected['ml2'].update({
{ 'mechanism_drivers': 'openvswitch,hyperv,l2population'
'mechanism_drivers': 'openvswitch,hyperv,l2population' })
}
)
for section, pairs in expected.iteritems(): for section, pairs in expected.iteritems():
ret = u.validate_config_data(unit, conf, section, pairs) ret = u.validate_config_data(unit, conf, section, pairs)
if ret: if ret:
message = "ml2 config error: {}".format(ret) message = "ml2 config error: {}".format(ret)
amulet.raise_status(amulet.FAIL, msg=message) amulet.raise_status(amulet.FAIL, msg=message)
def test_900_restart_on_config_change(self):
"""Verify that the specified services are restarted when the
config is changed."""
sentry = self.neutron_api_sentry
juju_service = 'neutron-api'
# Expected default and alternate values
set_default = {'debug': 'False'}
set_alternate = {'debug': 'True'}
# Services which are expected to restart upon config change,
# and corresponding config files affected by the change
services = {'neutron-server': '/etc/neutron/neutron.conf'}
# Make config change, check for service restarts
u.log.debug('Making config change on {}...'.format(juju_service))
mtime = u.get_sentry_time(sentry)
self.d.configure(juju_service, set_alternate)
sleep_time = 60
for s, conf_file in services.iteritems():
u.log.debug("Checking that service restarted: {}".format(s))
if not u.validate_service_config_changed(sentry, mtime, 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
self.d.configure(juju_service, set_default)

20
tests/tests.yaml Normal file
View File

@ -0,0 +1,20 @@
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-neutronclient
- python-novaclient
- python-pika
- python-swiftclient