diff --git a/src/test-requirements.txt b/src/test-requirements.txt index 0f71329..670c766 100644 --- a/src/test-requirements.txt +++ b/src/test-requirements.txt @@ -4,12 +4,14 @@ charm-tools>=2.0.0 bzr+lp:charm-helpers#egg=charmhelpers # BEGIN: Amulet OpenStack Charm Helper Requirements # Liberty client lower constraints +osprofiler amulet>=1.14.3,<2.0 bundletester>=0.6.1,<1.0 python-keystoneclient>=1.7.1,<2.0 python-glanceclient>=1.1.0,<2.0 python-openstackclient>=1.7.0,<2.0 python-mistralclient +python-heatclient>=0.8.0,<1.0 pika>=0.10.0,<1.0 distro-info # END: Amulet OpenStack Charm Helper Requirements diff --git a/src/tests/basic_deployment.py b/src/tests/basic_deployment.py index ca6886c..721fd5b 100644 --- a/src/tests/basic_deployment.py +++ b/src/tests/basic_deployment.py @@ -18,6 +18,8 @@ import json import subprocess import time +from mistralclient.api import client as mistral_client + import charmhelpers.contrib.openstack.amulet.deployment as amulet_deployment import charmhelpers.contrib.openstack.amulet.utils as os_amulet_utils @@ -25,9 +27,38 @@ import charmhelpers.contrib.openstack.amulet.utils as os_amulet_utils # Use DEBUG to turn on debug logging u = os_amulet_utils.OpenStackAmuletUtils(os_amulet_utils.DEBUG) +workbook_definition = """ +--- +version: '2.0' + +name: keystone_actions + +workflows: + get_first_keystone_project: + type: direct + + output: + project: + id: <% $.project_id %> + name: <% $.project_name %> + + tasks: + get_project_id: + action: keystone.projects_list + publish: + project_id: <% task(get_project_id).result[0].id %> + on-success: + - get_project_name + + get_project_name: + action: keystone.projects_get project=<% $.project_id %> + publish: + project_name: <% task(get_project_name).result.name %> +""" + class MistralBasicDeployment(amulet_deployment.OpenStackAmuletDeployment): - """Amulet tests on a basic sdn_charm deployment.""" + """Amulet tests on a basic Mistral deployment.""" def __init__(self, series, openstack=None, source=None, stable=False): """Deploy the entire test environment.""" @@ -39,7 +70,7 @@ class MistralBasicDeployment(amulet_deployment.OpenStackAmuletDeployment): self._deploy() u.log.info('Waiting on extended status checks...') - exclude_services = ['mysql', 'mongodb'] + exclude_services = ['percona-cluster', 'mongodb'] self._auto_wait_for_status(exclude_services=exclude_services) self._initialize_tests() @@ -47,13 +78,13 @@ class MistralBasicDeployment(amulet_deployment.OpenStackAmuletDeployment): def _add_services(self): """Add services - Add the services that we're testing, where sdn_charm is local, + Add the services that we're testing, where mistral 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': 'mistral'} other_services = [ - {'name': 'mysql'}, + {'name': 'percona-cluster', 'constraints': {'mem': '3072M'}}, {'name': 'rabbitmq-server'}, {'name': 'keystone'}, {'name': 'glance'}, @@ -64,11 +95,11 @@ class MistralBasicDeployment(amulet_deployment.OpenStackAmuletDeployment): def _add_relations(self): """Add all of the relations for the services.""" relations = { - 'keystone:shared-db': 'mysql:shared-db', - 'glance:shared-db': 'mysql:shared-db', + 'keystone:shared-db': 'percona-cluster:shared-db', + 'glance:shared-db': 'percona-cluster:shared-db', 'glance:identity-service': 'keystone:identity-service', 'glance:amqp': 'rabbitmq-server:amqp', - 'mistral:shared-db': 'mysql:shared-db', + 'mistral:shared-db': 'percona-cluster:shared-db', 'mistral:identity-service': 'keystone:identity-service', 'mistral:amqp': 'rabbitmq-server:amqp', } @@ -87,18 +118,31 @@ class MistralBasicDeployment(amulet_deployment.OpenStackAmuletDeployment): def _initialize_tests(self): """Perform final initialization before tests get run.""" # Access the sentries for inspecting service units - self.mistral_charm_sentry = self.d.sentry['sdn_charm'][0] - self.mysql_sentry = self.d.sentry['mysql'][0] + self.mistral_sentry = self.d.sentry['mistral'][0] + self.mysql_sentry = self.d.sentry['percona-cluster'][0] self.keystone_sentry = self.d.sentry['keystone'][0] self.rabbitmq_sentry = self.d.sentry['rabbitmq-server'][0] - self.mistral_charm_svcs = [ - 'sdn_charm-agent', 'sdn_charm-api'] - + self.mistral_svcs = [ + 'mistral-api', 'mistral-engine', 'mistral-executor'] # Authenticate admin with keystone endpoint self.keystone = u.authenticate_keystone_admin(self.keystone_sentry, user='admin', password='openstack', tenant='admin') + mistral_ep = self.keystone.service_catalog.url_for( + service_type='workflowv2', + endpoint_type='publicURL') + + keystone_ep = self.keystone.service_catalog.url_for( + service_type='identity', + endpoint_type='publicURL') + + self.mclient = mistral_client.client( + username='admin', + mistral_url=mistral_ep, + auth_url=keystone_ep, + project_name='admin', + api_key='openstack') def check_and_wait(self, check_command, interval=2, max_wait=200, desc=None): @@ -143,7 +187,7 @@ class MistralBasicDeployment(amulet_deployment.OpenStackAmuletDeployment): u.log.debug('Checking system services on units...') service_names = { - self.sdn_charm_sentry: self.sdn_charm_svcs, + self.mistral_sentry: self.mistral_svcs, } ret = u.validate_services_by_name(service_names) @@ -151,3 +195,34 @@ class MistralBasicDeployment(amulet_deployment.OpenStackAmuletDeployment): amulet.raise_status(amulet.FAIL, msg=ret) u.log.debug('OK') + + def test_mistral(self): + u.log.debug('Removing test workbook if present') + wbs = [wb.name for wb in self.mclient.workbooks.list()] + if 'keystone_actions' in wbs: + self.mclient.workbooks.delete('keystone_actions') + u.log.debug('Creating test workbook') + + self.mclient.workbooks.create(workbook_definition) + u.log.debug('Executing workbook') + exec_id = self.mclient.executions.create( + 'keystone_actions.get_first_keystone_project').id + for i in range(0, 20): + _execution = self.mclient.executions.get(exec_id) + u.log.debug('Execution status: {}'.format(_execution.state)) + if _execution.state == 'SUCCESS': + break + elif _execution.state == 'RUNNING': + time.sleep(10) + continue + else: + msg = "Unknown or failed execution stats {}".format( + _execution.state) + amulet.raise_status(amulet.FAIL, msg=msg) + else: + msg = "Timed out waiting for execution to complete" + amulet.raise_status(amulet.FAIL, msg=msg) + + exec_output = json.loads(_execution.output) + if exec_output['project']['name'] == "services": + u.log.debug('OK')